HDU 3065 病毒侵袭持续中 | AC自动机
//中文题好感动啊!!!
题解:
比较裸的AC自动机吧,对所有模式串建个AC自动机之后
用网站源码在上面跑匹配.
注意AC自动机建的时候字符集是26就好,遇到源码中别的字符直接回到Root
每个结尾节点记个CNT,我也不知道不记会不会跪
还有!注意这是个多组数据
#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define Z 27 #define M 2000010 using namespace std; struct node { int ch[Z],id,fail,cnt; void clear() { memset(ch,0,sizeof(ch)); cnt=id=fail=0; } }t[50010]; int n,cnt[1010],tot=1; char s[1010][60],text[M]; void insert(int id) { int p=1,len=strlen(s[id]); for (int i=0;i<len;i++) { if (t[p].ch[s[id][i]-'A']==0) t[t[p].ch[s[id][i]-'A']=++tot].clear(); p=t[p].ch[s[id][i]-'A']; } t[p].id=id; t[p].cnt++; } void BuildFail() { queue <int> q; t[1].fail=1; for (int i=0;i<26;i++) if (t[1].ch[i]==0) t[1].ch[i]=1; else t[t[1].ch[i]].fail=1,q.push(t[1].ch[i]); while (!q.empty()) { int u=q.front(),v,w; for (int i=0;i<26;i++) { v=t[t[u].fail].ch[i],w=t[u].ch[i]; if (w) t[w].fail=v,q.push(w); else t[u].ch[i]=v; } q.pop(); } } void query(char s[]) { int len=strlen(s),p=1; for (int i=0;i<len;i++) { if (s[i]>'Z' || s[i]<'A') { p=1; continue; } p=t[p].ch[s[i]-'A']; if (t[p].id!=0) cnt[t[p].id]+=t[p].cnt; } } void init() { memset(cnt,0,sizeof(cnt)); t[1].clear(); tot=1; } int main() { while (scanf("%d",&n)!=EOF) { init(); for (int i=1;i<=n;i++) scanf("%s",s[i]),insert(i); BuildFail(); getchar(); gets(text); query(text); for (int i=1;i<=n;i++) if (cnt[i]>0) printf("%s: %d\n",s[i],cnt[i]); } return 0; }