暑假- ac自动机-(C - 病毒侵袭持续中)

来源:互联网 发布:python 替换所有符号 编辑:程序博客网 时间:2024/06/05 00:58

明明题目没有说多组数据, 然后我就当作一组数据来做了。

看来看去代码都没有错,但是一提交就WA,害我该了一个下午。天啊!

去找题解才知道是多组数据。不要被省略”有多组数据“而欺骗了。

/* 题意:中文题,详见HDU 3065 思路:套AC自动机模板。 注意:建trie树时,字符串的信息(病毒编号)存放在最后一个字母的 value中,病毒特征码只包含“英文大写字符”,所以孩子节点只需26个没遇到一种病毒,则把(病毒出现次数的)数组对应的值+1。*/ #include<iostream>#include<cstring>#include<queue>#include<ctype.h>using namespace std;const int MAXM=2000100;//网站长度const int MAXN=50010;//病毒最多的需要的节点数char web[MAXM];//网站串char virus[1010][55];//病毒存放的数组int virusN[1010];//对应位置病毒出现的次数struct trie{int root,trieN;//根节点和当前树的最大节点int child[MAXN][26],value[MAXN],fail[MAXN];//孩子节点,节点值,失配数组int NewTrie()//新建节点{value[trieN]=0;memset(child[trieN],-1,sizeof(child[trieN]));return trieN++;}void init()//初始化{trieN=0;root=NewTrie();}void Insert(char s[],int k)//建树{int x=root;for(int i=0;s[i];i++){if(child[x][s[i]-'A']==-1){child[x][s[i]-'A']=NewTrie();}x=child[x][s[i]-'A'];}value[x]=k;//对应信息存放到最后一个字母中}void Build()//构建fail数组{int x;queue<int> q;fail[root]=root;for(int i=0;i<26;i++){if(child[root][i]==-1){child[root][i]=root;}else{fail[child[root][i]]=root;q.push(child[root][i]);}}while(!q.empty()){x=q.front();q.pop();for(int i=0;i<26;i++){if(child[x][i]==-1){child[x][i]=child[fail[x]][i];}else{fail[child[x][i]]=child[fail[x]][i];q.push(child[x][i]);}}}}void query(char s[])//网站匹配{int x=root,temp;for(int i=0;web[i];i++){if(!isupper(web[i]))//因为网站中字符都是ASCII码可见字符,而{                   //病毒只有大写字母,所以如果不是大写字母则x=0;            //可忽略,也可预处理先把web里面非大写字母去掉continue;}x=temp=child[x][s[i]-'A'];while(temp!=root){if(value[temp])//存在这种病毒{virusN[value[temp]]++;//对应位置+1}temp=fail[temp];}}}}ac;int main(){int n;while(cin>>n){ac.init();//初始化memset(virusN,0,sizeof(virusN));for(int i=1;i<=n;i++){cin>>virus[i];ac.Insert(virus[i],i);//建树}ac.Build();//构造failgetchar();cin.getline(web,MAXM);//输入网站,可能包含空格等ac.query(web);//匹配for(int i=1;i<=n;i++){if(virusN[i])//初始为0,只要出现过这种病毒则>0{cout<<virus[i];cout<<": "<<virusN[i]<<endl;}}}return 0;}


0 0
原创粉丝点击