AC自动机模板(【CJOJ1435】)

来源:互联网 发布:mac 系统 编辑:程序博客网 时间:2024/05/22 07:40

题面

Description

对,这就是裸的AC自动机。
要求:在规定时间内统计出模版字符串在文本中出现的次数。

Input

第一行:模版字符串的个数N。
第2->N+1行:N个字符串。(每个模版字符串的长度<=50)
第N+2行:一行很长的字符串。长的很。(使用AC自动机能在1s内计算出)

Output

共N行,每行输出一个模版及出现的次数。(之间有一个空格,按照输入顺序输出)

Sample Input

4
hers
her
his
she
shershisher

Sample Output

hers 1
her 2
his 1
she 2

Hint

所有字母均为小写
所给模版不会重复

题解

和前面Luogu那一道AC自动机的模板相同
只是要求解的东西不同。
到时候写完了AC自动机的详解再来粘链接

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<algorithm>using namespace std;struct Tree//字典树 {     int fail;//失配指针     int vis[26];//子节点的位置     int end;//标记以这个节点结尾的单词编号 }AC[1000000];//Trie树int cnt=0;//Trie的指针 int Ans[1000000];//所有单词的出现次数 string s[1000000];inline void Build(string s,int Num){        int l=s.length();        int now=0;//字典树的当前指针         for(int i=0;i<l;++i)//构造Trie树        {                if(AC[now].vis[s[i]-'a']==0)//Trie树没有这个子节点                   AC[now].vis[s[i]-'a']=++cnt;//构造出来                now=AC[now].vis[s[i]-'a'];//向下构造         }        AC[now].end=Num;//标记单词结尾 }void Get_fail()//构造fail指针{        queue<int> Q;//队列         for(int i=0;i<26;++i)//第二层的fail指针提前处理一下        {               if(AC[0].vis[i]!=0)               {                   AC[AC[0].vis[i]].fail=0;//指向根节点                   Q.push(AC[0].vis[i]);//压入队列                }        }        while(!Q.empty())//BFS求fail指针         {              int u=Q.front();              Q.pop();              for(int i=0;i<26;++i)//枚举所有子节点              {                      if(AC[u].vis[i]!=0)//存在这个子节点                      {                              AC[AC[u].vis[i]].fail=AC[AC[u].fail].vis[i];                                  //子节点的fail指针指向当前节点的                                  //fail指针所指向的节点的相同子节点                               Q.push(AC[u].vis[i]);//压入队列                       }                      else//不存在这个子节点                       AC[u].vis[i]=AC[AC[u].fail].vis[i];                      //当前节点的这个子节点指向当                      //前节点fail指针的这个子节点               }        }}int AC_Query(string s)//AC自动机匹配{        int l=s.length();        int now=0,ans=0;        for(int i=0;i<l;++i)        {                now=AC[now].vis[s[i]-'a'];//向下一层                for(int t=now;t;t=AC[t].fail)//循环求解                         Ans[AC[t].end]++;        }        return ans;}int main(){     int n;     cin>>n;     for(int i=1;i<=n;++i)     {            cin>>s[i];            Build(s[i],i);     }     AC[0].fail=0;//结束标志      Get_fail();//求出失配指针     cin>>s[0];//文本串      AC_Query(s[0]);     for(int i=1;i<=n;++i)     {            cout<<s[i]<<' ';            cout<<Ans[i]<<endl;     }     return 0;}
原创粉丝点击