制作失配函数时注意两点:
一是从上往下计算,开个队列~
二是采用大白书的“一视同仁”法提高效率,就是一条边走不下去时直接把这条边接在失配函数的对应边上。
废话少说上代码~
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cctype> 6 //#include<iostream> 7 using namespace std; 8 9 #define maxt 1000011 10 #define maxs 500011 11 #define maxc 26 12 int n; 13 char s[maxs],T[maxt];int Case; 14 struct Trie 15 { 16 int size,ch[maxs][maxc],fail[maxs],last[maxs],val[maxs],ans;bool vis[maxs]; 17 void clear() 18 { 19 memset(ch[0],0,sizeof(ch[0])); 20 memset(vis,0,sizeof(vis)); 21 val[0]=0;size=0;ans=0; 22 } 23 int idx(char c) {return c-'a';} 24 void insert(char* s) 25 { 26 int now=0,ls=strlen(s); 27 for (int i=0;i<ls;i++) 28 { 29 int id=idx(s[i]); 30 if (!ch[now][id]) 31 { 32 ch[now][id]=++size; 33 memset(ch[size],0,sizeof(ch[size])); 34 val[size]=0; 35 } 36 now=ch[now][id]; 37 } 38 val[now]++; 39 } 40 void make_fail() 41 { 42 int que[maxs],head,tail; 43 head=tail=0; 44 for (int i=0;i<maxc;i++) 45 { 46 int u=ch[0][i]; 47 if (u) 48 { 49 fail[u]=0; 50 que[tail++]=u; 51 last[u]=0; 52 } 53 } 54 while (head<tail) 55 { 56 int x=que[head++]; 57 for (int i=0;i<maxc;i++) 58 { 59 int u=ch[x][i]; 60 if (!u) {ch[x][i]=ch[fail[x]][i];continue;} 61 que[tail++]=u; 62 fail[u]=ch[fail[x]][i]; 63 last[u]=val[fail[u]]?fail[u]:last[fail[u]]; 64 } 65 } 66 } 67 void play(int x) 68 { 69 if (!x || vis[x]) return; 70 ans+=val[x]; 71 vis[x]=1; 72 play(last[x]); 73 } 74 void AC() 75 { 76 make_fail(); 77 int lt=strlen(T),now=0; 78 for (int i=0;i<lt;i++) 79 { 80 int id=idx(T[i]); 81 now=ch[now][id]; 82 if (val[now]) play(now); 83 else if (last[now]) play(last[now]); 84 } 85 printf("%d ",ans); 86 } 87 }trie; 88 int main() 89 { 90 scanf("%d",&Case); 91 while (Case--) 92 { 93 trie.clear(); 94 scanf("%d",&n); 95 for (int i=1;i<=n;i++) scanf("%s",s),trie.insert(s); 96 scanf("%s",T); 97 trie.AC(); 98 } 99 return 0; 100 }