AC自动机
class AC { public: int next[maxn][26], lst[maxn], fail[maxn], val[maxn]; int sz, root; void init() { root = sz = 0; for (int i=0; i<26; ++i) next[sz][i] = 0; val[sz] = 0; sz = 1; } inline int getid(char ch) { return ch-'a'; } inline int newnode() { for (int i=0; i<26; ++i) next[sz][i] = 0; val[sz] = 0; return sz++; } void insert(char s[]) { int rt, i, id, len; rt = 0; len = strlen(s); for (i=0; i<len; ++i) { id = getid(s[i]); if (!next[rt][id]) next[rt][id] = newnode(); rt = next[rt][id]; } val[rt]++; } void build() { queue<int> q; int i, rt, id; fail[root] = root; lst[root] = root; for (i=0; i<26; ++i) { if (!next[root][i]) next[root][i] = root; else { fail[next[root][i]] = root; q.push(next[root][i]); lst[next[root][i]] = val[fail[next[root][i]]] ? fail[next[root][i]] : lst[fail[next[root][i]]]; } } while (!q.empty()) { rt = q.front(); q.pop(); for (i=0; i<26; ++i) { if (!next[rt][i]) next[rt][i] = next[fail[rt]][i]; else { fail[next[rt][i]] = next[fail[rt]][i]; q.push(next[rt][i]); lst[next[rt][i]] = val[fail[next[rt][i]]] ? fail[next[rt][i]] : lst[fail[next[rt][i]]]; } } } } int query(char s[]) { int i, rt, tmp, now = 0, res = 0, len = strlen(s); for (i=0; i<len; ++i) { now = next[now][getid(s[i])]; tmp = now; while (tmp) { res += val[tmp]; val[tmp] = 0; tmp = lst[tmp]; } } return res; } };