题意:
问母串中出现多少个模式串
注意ac自动机的节点总数
#include <stdio.h> #include <string.h> #include <queue> using namespace std; inline int Max(int a,int b){return a>b?a:b;} inline int Min(int a,int b){return a>b?b:a;} int ANS; #define N 1000010 #define maxnode 250001 #define sigma_size 26 struct Trie{ int ch[maxnode][sigma_size]; int val[maxnode]; int last[maxnode]; int f[maxnode]; int sz; void init(){ sz=1; memset(ch,0,sizeof(ch)); memset(val, 0, sizeof(val)); memset(f,0,sizeof(f)); memset(last,0,sizeof(last)); } int idx(char c){ return c-'a'; } void print(int j){ if(j){ printf("%d: %d ", j, val[j]); print(last[j]); } } void Creat(char *s){ int u = 0, len = strlen(s); for(int i = 0;i < len;i++){ int c = idx(s[i]); if(!ch[u][c]) ch[u][c] = sz++; u = ch[u][c]; } val[u] ++; } void getFail(){ queue<int> q; for(int i = 0; i<sigma_size; i++) if(ch[0][i]) q.push(ch[0][i]); while(!q.empty()){ int r = q.front(); q.pop(); for(int c = 0; c<sigma_size; c++){ int u = ch[r][c]; if(!u)continue; q.push(u); int v = f[r]; while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环 f[u] = ch[v][c]; last[u] = val[f[u]] ? f[u] : last[f[u]]; } } } void find(char *T){ int len = strlen(T), j = 0; for(int i = 0; i < len; i++){ int c = idx(T[i]); while(j && ch[j][c]==0) j = f[j]; j = ch[j][c]; int temp = j; while(temp && val[temp]){ ANS += val[temp]; val[temp] = 0; temp = f[temp]; } } } }; Trie ac; char S1[N]; int Slen; void InputString(){ scanf("%s",S1); Slen = strlen(S1); S1[Slen]=' '; } int main(){ int T,i,j,n;scanf("%d",&T); while(T--){ ac.init(); scanf("%d",&n); while(n--){ scanf("%s",S1); ac.Creat(S1); } ac.getFail(); InputString(); ANS = 0; ac.find(S1); printf("%d ",ANS); } return 0; } /* 1 5 she he say shr her yasherhs ans: 3 */