poj 4052(ac自动机)
题意:自己百度吧!!
分析:就是通过它的fail指针来找出它的子串就行了,这题其实不难的。这好像还是金华邀请赛的题哦!
代码实现:
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<queue> using namespace std; struct node{ int next[26]; int fail; int num; void init() { memset(next,0,sizeof(next)); fail=0; num=0; } }a[3000010]; char keyword[2600][1200]; char S[5200001],temp[5200001]; int visited[3505]; int tot,n; int ok[3000010]; void chushihua()//初始化 { tot=0; a[0].init(); memset(visited,0,sizeof(visited)); } void insert(char *str,int biaohao)//建立字典树 { int index,p=0; for(;*str!='\0';str++) { index=*str-'A'; if(a[p].next[index]==0) { a[++tot].init(); a[p].next[index]=tot; } p=a[p].next[index]; } a[p].num=biaohao; } void build_fail()//建立trie图 { queue<int>Q; int p,cur,son,i; Q.push(0); while(!Q.empty()) { p=Q.front(); Q.pop(); for(i=0;i<26;i++) { if(a[p].next[i]!=0) { son=a[p].next[i]; cur=a[p].fail; if(p==0) a[son].fail=0; else { while(cur&&a[cur].next[i]==0) cur=a[cur].fail; a[son].fail=a[cur].next[i]; } Q.push(son); } else a[p].next[i]=a[a[p].fail].next[i]; } } } void change(char str[]) { int i,len=0,k=0; for(i=0;str[i]!='\0';i++) { if(str[i]>='A'&&str[i]<='Z') temp[len++]=str[i]; else { i++; k=0;//开始的时候这里没加,一直wa,细节啊 k=k+str[i]-'0'; i++; while(str[i]>='0'&&str[i]<='9') { k=k*10+str[i]-'0'; i++; } while(k--) temp[len++]=str[i]; i++; } } temp[len]='\0'; strcpy(str,temp); } void solve1()//在主串里出现过的全部标记了 { int i,index,p=0,j; for(i=0;S[i]!='\0';i++) { index=S[i]-'A'; p=a[p].next[index]; if(a[p].num) { visited[a[p].num]=1; continue;//它的子串肯定就不用标记了 } for(j=p;j!=0&&ok[j]==0;j=a[j].fail) { ok[j]=1; visited[a[j].num]=1; } } } void solve2(char S[],int biaohao)//去掉子串 { int i,index,p=0,j; for(i=0;S[i]!='\0';i++) { index=S[i]-'A'; p=a[p].next[index]; for(j=p;j!=0&&ok[j]==0;j=a[j].fail) { if(a[j].num&&a[j].num!=biaohao) { visited[a[j].num]=0; ok[j]=1; } } } } int main() { int T,i,res; scanf("%d",&T); while(T--) { chushihua(); res=0; scanf("%d",&n); getchar(); for(i=1;i<=n;i++) { scanf("%s",keyword[i]); change(keyword[i]);//把畸形的字符串变成正常的 insert(keyword[i],i); } build_fail(); scanf("%s",S); change(S); memset(ok,0,sizeof(ok)); solve1(); memset(ok,0,sizeof(ok)); for(i=1;i<=n;i++) if(visited[i]==1) solve2(keyword[i],i); for(i=1;i<=n;i++) if(visited[i]==1) res++; printf("%d\n",res); } return 0; }
posted on 2013-08-05 12:55 后端bug开发工程师 阅读(904) 评论(2) 编辑 收藏 举报