BZOJ 3172: [Tjoi2013]单词 (AC自动机)

跟这道题一模一样,而且不强制在线,所以先打标记然后上传就行了.

CODE

#include<bits/stdc++.h>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
	char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
	for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 1000205;
const int C = 27;
int n, m, node[MAXN];
struct Aho_Corasick {
	int ch[MAXN][C], fail[MAXN], tot, q[MAXN];
	inline int insert(char *s) {
		int r = 0, indx;
		while(*s) {
			if(!ch[r][indx=(*s++)-'a'])
				ch[r][indx] = ++tot;
			r = ch[r][indx];
		}
		return r;
	}
	inline void build() {
		int r = 0, head = 0, tail = 0;
		fail[q[tail++]=r] = -1;
		while(head < tail) {
			r = q[head++];
			for(int v, indx = 0; indx < C; ++indx)
				if((v=ch[r][indx])) {
					q[tail++] = v;
					fail[v] = (r == 0 ? 0 : ch[fail[r]][indx]);
				}
				else ch[r][indx] = (r == 0 ? 0 : ch[fail[r]][indx]);
		}
	}
	int ans[MAXN];
	void modify(char *s) {
		int r = 0, indx;
		while(*s)
			++ans[r = ch[r][indx=(*s++)-'a']];
        //直接用上面的队列
        for(int i = tot; i; --i)
            ans[fail[q[i]]] += ans[q[i]];
	}
}trie;
char s[MAXN], S[MAXN];
int main() {
	read(n); int now = 0;
	for(int i = 1; i <= n; ++i) {
		scanf("%s", s), node[i] = trie.insert(s);
		for(int j = 0; s[j]; ++j)
            S[now++] = s[j];
        S[now++] = 'z'+1; //插一个特殊符号
	}
	trie.build();
	trie.modify(S);
	for(int i = 1; i <= n; ++i) printf("%d
", trie.ans[node[i]]);
}


原文地址:https://www.cnblogs.com/Orz-IE/p/12039317.html