The Aho-Corasick Automaton is a data structure that maintains a set of strings in by maintaining a deterministic finite automaton that accepts and only accepts strings containing a string from as a suffix.

Specifically, let be the set of the prefixes of the strings in , and let

and let be a function in satisfying

Lemma

Let , then applying the lemma yields that is a deterministic finite automaton that accepts and only accepts strings containing a string from as a suffix.

This costs a space of .

Build

Build builds an Aho-Corasick Automaton for in time and space.

Algorithm

Lemma

Let

Then

Lemma

  1. Build a Trie for .
  2. For each prefix in increasing order of length, apply the lemmas to find the and for .

This algorithm solves the problem in time and space.

void build(int n, const std::vector<std::string> &s) {
	next.assign(2, {});
	next[0].fill(1);
	f.assign(2, false);
 
	for (int i = 0; i < n; i++) {
		int o = 1;
		for (char c : s[i]) {
			if (!next[o][c]) {
				next[o][c] = next.size();
				next.emplace_back();
				f.push_back(false);
			}
			o = next[o][c];
		}
		f[o] = true;
	}
 
	std::vector fail(next.size(), 0);
 
	std::queue<int> q;
	q.push(1);
	while (!q.empty()) {
		int o = q.front();
		q.pop();
 
		f[o] = f[o] || f[fail[o]];
		for (char c : alphabet) {
			if (next[o][c]) {
				fail[next[o][c]] = next[fail[o]][c];
				q.push(next[o][c]);
			} else {
				next[o][c] = next[fail[o]][c];
			}
		}
	}
}

Find

Find checks if in time and space.

Algorithm

Running on yields an algorithm that solves the problem in time and space.

bool find(const std::string &s) {
	int o = 1;
	for (char c : s) {
		o = next[o][c];
	}
	return f[o];
}