南阳oj 1085 AC自动机 一般(有点坑)

来源:互联网 发布:淘宝网店流量 编辑:程序博客网 时间:2024/06/11 17:13

点击打开题目


题目意思很明确,AC自动机没什么好说的,不过这个题有个地方有点坑,就是有些同样的单词会多次输入,而且输出的时候按照顺序来,只要满足频率最高,就算同样的单词已经输出了还要再输出

先贴wa代码:

 #include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<cstdlib>using namespace std;struct Trie{int count;int num;struct Trie *next[26];struct Trie *fail;};struct node{int count;}a[200];int Max;char str[1000001];Trie *newset(){Trie *p=(Trie*)malloc(sizeof(Trie));p->count=p->num=0;p->fail=NULL;for(int i=0;i<26;i++)p->next[i]=NULL;return p;}void insert(char s[200],Trie *root,int num){int i,t,len=strlen(s);Trie *p=root;for(i=0;i<len;i++){t=s[i]-'a';if(p->next[t]==NULL)p->next[t]=newset();p=p->next[t];}p->count++;p->num=num;}void build_AC(Trie *root){int i,t;Trie *p,*q;queue<Trie*>Q;Q.push(root);while(!Q.empty()){p=Q.front();Q.pop();for(i=0;i<26;i++)if(p->next[i]){if(p==root)p->next[i]->fail=root;else{q=p->fail;while(q){if(q->next[i]){p->next[i]->fail=q->next[i];break;}q=q->fail; }if(!q)p->next[i]->fail=root;}Q.push(p->next[i]);}}}void query_AC(Trie *root){int i,j,t,len=strlen(str);Trie *p,*q;p=root;for(i=0;i<len;i++){t=str[i]-'a';while(!p->next[t]&&p!=root)p=p->fail;if(p->next[t]){p=p->next[t];if(p->count){j=p->num;a[j].count++;if(Max<a[j].count)Max=a[j].count;}q=p;while(q){q=q->fail;if(q&&q!=root&&q->count!=0){j=q->num;a[j].count++;if(Max<a[j].count)Max=a[j].count;}}}}}int main(){int T;scanf("%d",&T);while(T--){int n,i;Trie *root=newset();char s[200][200];scanf("%d",&n);for(i=0;i<n;i++){scanf("%s",s[i]);insert(s[i],root,i);a[i].count=0;}scanf("%s",str);build_AC(root);Max=0;query_AC(root);printf("%d\n",Max);for(i=0;i<n;i++)if(a[i].count==Max)printf("%s\n",s[i]);}}        


AC代码:

#include<cstdio>#include<cstring>#include<queue>#include<cstdlib>using namespace std;struct Trie{int count;int num[20];//记录单词的序号 int tot;//可能会有重复的单词 struct Trie *next[26];struct Trie *fail;};struct node{int count;}a[200];//记录每个序号的单词出现的频率int Max;char str[1000001];Trie *newset(){Trie *p=(Trie*)malloc(sizeof(Trie));p->count=p->tot=0;p->fail=NULL;for(int i=0;i<26;i++)p->next[i]=NULL;return p;}void insert(char s[200],Trie *root,int num){int i,t,len=strlen(s);Trie *p=root;for(i=0;i<len;i++){t=s[i]-'a';if(p->next[t]==NULL)p->next[t]=newset();p=p->next[t];}p->count++;p->tot++;p->num[p->tot]=num;}void build_AC(Trie *root){int i,t;Trie *p,*q;queue<Trie*>Q;Q.push(root);while(!Q.empty()){p=Q.front();Q.pop();for(i=0;i<26;i++)if(p->next[i]){if(p==root)p->next[i]->fail=root;else{q=p->fail;while(q){if(q->next[i]){p->next[i]->fail=q->next[i];break;}q=q->fail; }if(!q)p->next[i]->fail=root;}Q.push(p->next[i]);}}}void query_AC(Trie *root){int i,j,t,len=strlen(str);Trie *p,*q;p=root;for(i=0;i<len;i++){t=str[i]-'a';while(!p->next[t]&&p!=root)p=p->fail;if(p->next[t]){p=p->next[t];if(p->count){for(int k=1;k<=p->tot;k++)//可能会有重复的单词,每个序号都要统计 {j=p->num[k];a[j].count++;if(Max<a[j].count)Max=a[j].count;}}q=p;while(q){q=q->fail;if(q&&q!=root&&q->count!=0){for(int k=1;k<=q->tot;k++){j=q->num[k];a[j].count++;if(Max<a[j].count)Max=a[j].count;}}}}}}int main(){int T;scanf("%d",&T);while(T--){int n,i;Trie *root=newset();char s[200][200];scanf("%d",&n);for(i=0;i<n;i++){scanf("%s",s[i]);insert(s[i],root,i);a[i].count=0;}scanf("%s",str);build_AC(root);Max=0;query_AC(root);printf("%d\n",Max);for(i=0;i<n;i++)if(a[i].count==Max)printf("%s\n",s[i]);}}

原创粉丝点击