http://acm.hdu.edu.cn/showproblem.php?pid=5384
1 5 6 orz sto kirigiri danganronpa ooooo o kyouko dangan ronpa ooooo ooooo
1 1 0 3 7
/** hdu5384 AC自动机模板题,统计模式串在给定串中出现的个数 */ #include<string.h> #include<algorithm> #include<iostream> #include<stdio.h> #include<queue> using namespace std; char str[100010][10010]; int num[100010],n,m; struct Trie { int next[10010*50][28],fail[10010*50],end[10010*50]; int root,L; int newnode() { for(int i=0; i<26; i++) { next[L][i]=-1; } end[L++]=-1; return L-1; } void init() { L=0; root=newnode(); } void insert(char *s) { int len=strlen(s); int now=root; for(int i=0; i<len; i++) { if(next[now][s[i]-'a']==-1) { next[now][s[i]-'a']=newnode(); } now=next[now][s[i]-'a']; } if(end[now]==-1)///标记模式串出现的次数 { end[now]=1; } else { end[now]++; } } void build() { queue<int>Q; fail[root]=root; for(int i=0; i<26; i++) { if(next[root][i]==-1) { next[root][i]=root; } else { fail[next[root][i]]=root; Q.push(next[root][i]); } } while(!Q.empty()) { // printf("**\n"); int now=Q.front(); Q.pop(); for(int i=0; i<26; i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } } void query(char* s) { memset(num,0,sizeof(num)); int len=strlen(s); int now=root; for(int i=0; i<len; i++) { now=next[now][s[i]-'a']; int temp=now; while(temp!=root) { if(end[temp]!=-1)///统计所有模式串出现的次数,num数组在0~m之间定能取到所有end[temp]必不大于m { num[end[temp]]+=end[temp]; } temp=fail[temp]; } } int ans=0; for(int i=0; i<=m; i++) { if(num[i]>0) ans+=num[i]; } printf("%d\n",ans); } } ac; char s[10005]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%s",str[i]); } ac.init(); for(int i=0; i<m; i++) { scanf("%s",s); ac.insert(s); } ac.build(); //printf("**\n"); for(int i=0; i<n; i++) { ac.query(str[i]); } } return 0; }