今天是第二天集训。(其实已经是第三天了,只是昨天并没有机会来写总结,现在补上)
上午大家心情都很愉快,因为老师讲了splay树和ac自动机。
但到了下午,我们的教练竟然跑出去耍了(excuse me?),害的我们在一些不懂的地方冥思苦想浪费时间,效率极其低下,所以说只做了点模板题,以后这方面的知识还需要多多练习0.0
1.ac自动机
这东西是kmp的升级版本,由一个模式串升级到了多个模式串,效率依然高。
只要掌握了kmp,ac自动机一般不会有问题。哦,当然你也必须会trie树,这是自动机的基础
首先,和kmp一样,构造fail数组,也就是next数组。注意:这个fail数组不止能够跳到自己的最大相同前缀上,还能跳到别的串。
有了fail数组,就可以匹配了,过程也和kmp类似,只不过加一些处理令得模式串之间可以互相到达
所以,以上我说的全是废话[滑稽]。
话不多说,上代码(标准模板)
CODE: HDU2222
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10005 4 int tr[N*50][26],ls[N*50],n,tot,f[N*50],val[N*50],ans; 5 char s[1000005],ch[55]; 6 7 void adtr(){ 8 int i=0,x=0; 9 while(ch[i]){ 10 int k=ch[i]-'a'; 11 if(!tr[x][k])tr[x][k]=++tot; 12 x=tr[x][k];i++; 13 } 14 val[x]++; 15 } 16 17 void getfail(){ 18 queue<int>q; 19 int u,v,rt; 20 for(int i=0;i<26;i++)if(tr[0][i])q.push(tr[0][i]),f[tr[0][i]]=ls[tr[0][i]]=0; 21 while(!q.empty()){ 22 rt=q.front();q.pop(); 23 for(int i=0;i<26;i++){ 24 int u=tr[rt][i]; 25 if(!u){tr[rt][u]=tr[f[rt]][u];continue;} 26 q.push(u); 27 v=f[rt]; 28 while(v&&!tr[v][i])v=f[v]; 29 f[u]=tr[v][i]; 30 if(val[f[u]])ls[u]=f[u]; 31 else ls[u]=ls[f[u]]; 32 } 33 } 34 } 35 36 void make(int x){ 37 if(!x)return; 38 if(val[x])ans+=val[x],val[x]=0; 39 make(ls[x]); 40 } 41 42 void ac(){ 43 int x=0; 44 for(int i=0;s[i];i++){ 45 int k=s[i]-'a'; 46 //while(x&&!tr[x][k])x=f[x]; 47 /*上一句可以省略的原因是 getfail()函数中的这一句 : 48 if(!u){tr[rt][u]=tr[f[rt]][u];continue;} 49 已经通过迭代求出了最近的有k的串 */ 50 x=tr[x][k]; 51 if(val[x])make(x); 52 else if(ls[x])make(ls[x]); 53 } 54 } 55 56 int main(){ 57 int T;cin>>T; 58 while(T--){ 59 memset(val,0,sizeof(val)); 60 memset(tr,0,sizeof(tr)); 61 ans=tot=0;scanf("%d",&n); 62 for(int i=1;i<=n;i++)scanf("%s",ch),adtr(); 63 getfail();scanf("%s",s);ac(); 64 printf("%d\n",ans); 65 } 66 }