2017.10.6 单词 思考记录

来源:互联网 发布:全球云计算市场格局 编辑:程序博客网 时间:2024/06/06 21:07

少有的会做的ac自动机题

、这个题是匹配模式串、

所以就不需要匹配的过程,只需要建出fail树,然后直接拓扑

由于每次加进去一个单词,这个单词的每一个字母都有可能作为最后一个字母影响他的失配,所以词路径上的每个字母都需要标记

然后失配是保证了后缀相等,所以如果失配是词,则这个点的所有继承过来的标记都可以传给失配


由于fail是一棵树,所以需要拓扑来保证每一个点都被标记充分


码:

#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<cstring>using namespace std;int i,l,rt,ch[1000005][26],j,n,ans[205],tot,bj[1000005],sp[1000005],rd[1000005];char str[205][1000005];queue<int>q;vector<int>v[1000005];void jia(){int o=rt;for(j=0;j<l;j++){int zm=str[i][j]-'a';if(ch[o][zm]==0)ch[o][zm]=++tot;o=ch[o][zm];bj[o]++;}v[o].push_back(i);}void shipei(){q.push(rt);while(!q.empty()){int o=q.front();q.pop();//bj[o]=v[o].size();for(i=0;i<26;i++){if(o==0&&ch[o][i]!=0){q.push(ch[o][i]);}else   if(ch[o][i]!=0){   int p=sp[o];while(ch[p][i]==0&&p!=0)p=sp[p];  sp[ch[o][i]]=ch[p][i];  rd[ch[p][i]]++;q.push(ch[o][i]);}}}return;}void tuopu(){for(i=1;i<=tot;i++){if(rd[i]==0){q.push(i);}}while(!q.empty()){int o=q.front();q.pop();for(j=0;j<v[o].size();j++)//统计一波答案{ans[v[o][j]]+=bj[o];}rd[sp[o]]--;bj[sp[o]]+=bj[o];if(rd[sp[o]]==0&&sp[o]!=0)q.push(sp[o]);}}int main(){scanf("%d",&n);for(i=1;i<=n;i++){scanf("%s",str[i]);l=strlen(str[i]);jia();}shipei();tuopu();for(i=1;i<=n;i++){printf("%d\n",ans[i]);}} 




原创粉丝点击