zoukankan      html  css  js  c++  java
  • 洛谷 P3808 【模板】AC自动机(简单版)洛谷 P3796 【模板】AC自动机(加强版)

    https://www.cnblogs.com/gtarcoder/p/4820560.html

    每个节点的后缀指针fail指针指向:

    例如he,she,his,hers的例子(见蓝书P214):

    7号点表示串his,将其头部去掉得到is但不存在该节点,再次将其头部去掉得到s,存在该节点,因此7号的后缀指针指向表示s的3号

    5号点表示串she,将其头部去掉得到he,存在该节点,因此5号的后缀指针指向表示he的2号

    从根节点到节点P可以得到一个字符串S,节点P的前缀指针定义为 指向树中出现过的S的最长后缀(不能等于S)

    可以将trie上所有不存在的边u--(ch)-->v都补全为其fail指针指向的同类型边(f[u]--(ch)-->v'得到u--(ch)-->v')。(减少特判且方便递推)

    每个节点的lst,与fail的区别在于,其指向的点表示的字符串一定是原来字符串集合中某一个完整的串(或空串),而fail则只要求原集合中某串的前缀即可

    P3808中:由于只计算“出现过的”,所以某个算过贡献后要赋为0

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 char *s[1001000],tttt[2000100],*sp=tttt,s2[1000100];
      7 int n;
      8 //namespace AC
      9 //{
     10 //    int ch[1001000][26],sum[1001000],f[1001000],root,mem,lst[1000100];
     11 //    void insert(char *x)
     12 //    {
     13 //        if(!root)    root=++mem;
     14 //        int now=root,u;
     15 //        for(;*x;x++)
     16 //        {
     17 //            u=*x-'a';
     18 //            if(!ch[now][u])    ch[now][u]=++mem;
     19 //            now=ch[now][u];
     20 //        }
     21 //        sum[now]++;
     22 //    }
     23 //    void build()
     24 //    {
     25 //        int c,t,u,v;
     26 //        queue<int> q;
     27 //        f[root]=root;
     28 //        for(c=0;c<26;c++)
     29 //        {
     30 //            u=ch[root][c];
     31 //            if(u)    {f[u]=root;q.push(u);lst[u]=root;}
     32 //        }
     33 //        while(!q.empty())
     34 //        {
     35 //            t=q.front();q.pop();
     36 //            for(c=0;c<26;c++)
     37 //            {
     38 //                u=ch[t][c];
     39 //                if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     40 //                q.push(u);
     41 //                v=f[t];
     42 //                while(v!=root&&!ch[v][c])    v=f[v];
     43 //                f[u]=ch[v][c];
     44 //                lst[u]=sum[u]?f[u]:lst[f[u]];
     45 //            }
     46 //        }
     47 //    }
     48 //    void search(char *x)
     49 //    {
     50 //        int j=root;
     51 //        for(;*x;x++)
     52 //        {
     53 //            c=*x-'a';
     54 //            if(sum[c])
     55 //        }
     56 //    }
     57 //}
     58 //注释掉的是root任意值的情况,未完成,以下程序认为root为0号点
     59 namespace AC
     60 {
     61     int ch[1001000][26],sum[1001000],f[1001000],mem,lst[1000100];
     62     void insert(char *x)
     63     {
     64         int now=0,u;
     65         for(;*x;x++)
     66         {
     67             u=*x-'a';
     68             if(!ch[now][u])    ch[now][u]=++mem;
     69             now=ch[now][u];
     70         }
     71         sum[now]++;
     72     }
     73     void build()
     74     {
     75         int c,t,u;
     76         queue<int> q;
     77         f[0]=0;
     78         for(c=0;c<26;c++)
     79         {
     80             u=ch[0][c];
     81             if(u)    {f[u]=0;q.push(u);lst[u]=0;}
     82         }
     83         while(!q.empty())
     84         {
     85             t=q.front();q.pop();
     86             for(c=0;c<26;c++)
     87             {
     88                 u=ch[t][c];
     89                 if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     90                 q.push(u);
     91                 f[u]=ch[f[t]][c];
     92                 lst[u]=sum[f[u]]?f[u]:lst[f[u]];
     93             }
     94         }
     95     }
     96     int ans;
     97     void get_ans(int j)
     98     {
     99         while(j)
    100         {
    101             ans+=sum[j];
    102             sum[j]=0;
    103             j=lst[j];
    104         }
    105     }
    106     int count(char *x)
    107     {
    108         ans=0;
    109         int j=0,c;
    110         for(;*x;x++)
    111         {
    112             c=*x-'a';
    113             j=ch[j][c];
    114             get_ans(j);
    115         }
    116         return ans;
    117     }
    118 }
    119 int main()
    120 {
    121     int i;
    122     scanf("%d",&n);
    123     for(i=1;i<=n;i++)
    124     {
    125         s[i]=sp;scanf("%s",s[i]);sp+=strlen(s[i])+1;
    126         AC::insert(s[i]);
    127     }
    128     AC::build();
    129     scanf("%s",s2);
    130     printf("%d",AC::count(s2));
    131     return 0;
    132 }

    P3796

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<queue>
      5 #include<vector>
      6 #include<map>
      7 #include<string>
      8 using namespace std;
      9 char *s[160],tttt[20000],*sp,s2[1000100];
     10 int n;
     11 namespace AC
     12 {
     13     int ch[20000][26],sum[20000],f[20000],mem,lst[20000],ans[20000];
     14     void clear()
     15     {
     16         int i,j;
     17         for(i=0;i<=mem;i++)
     18         {
     19             for(j=0;j<26;j++)    ch[i][j]=0;
     20             sum[i]=f[i]=lst[i]=ans[i]=0;
     21         }
     22         mem=0;
     23     }
     24     int insert(char *x)
     25     {
     26         int now=0,u;
     27         for(;*x;x++)
     28         {
     29             u=*x-'a';
     30             if(!ch[now][u])    ch[now][u]=++mem;
     31             now=ch[now][u];
     32         }
     33         sum[now]++;
     34         return now;
     35     }
     36     void build()
     37     {
     38         int c,t,u;
     39         queue<int> q;
     40         f[0]=0;
     41         for(c=0;c<26;c++)
     42         {
     43             u=ch[0][c];
     44             if(u)    {f[u]=0;q.push(u);lst[u]=0;}
     45         }
     46         while(!q.empty())
     47         {
     48             t=q.front();q.pop();
     49             for(c=0;c<26;c++)
     50             {
     51                 u=ch[t][c];
     52                 if(!u)    {ch[t][c]=ch[f[t]][c];continue;}
     53                 q.push(u);
     54                 f[u]=ch[f[t]][c];
     55                 lst[u]=sum[f[u]]?f[u]:lst[f[u]];
     56             }
     57         }
     58     }
     59     void get_ans(int j)
     60     {
     61         while(j)
     62         {
     63             ans[j]+=sum[j];
     64             j=lst[j];
     65         }
     66     }
     67     void work(char *x)
     68     {
     69         int j=0,c;
     70         for(;*x;x++)
     71         {
     72             c=*x-'a';
     73             j=ch[j][c];
     74             get_ans(j);
     75         }
     76     }
     77 }
     78 int pos[20000];
     79 int a1,anss;
     80 int main()
     81 {
     82     int i;
     83     while(1)
     84     {
     85         scanf("%d",&n);
     86         if(n==0)    break;
     87         AC::clear();
     88         sp=tttt;
     89         for(i=1;i<=n;i++)
     90         {
     91             s[i]=sp;scanf("%s",s[i]);sp+=strlen(s[i])+1;
     92             pos[i]=AC::insert(s[i]);
     93         }
     94         AC::build();
     95         scanf("%s",s2);
     96         AC::work(s2);a1=anss=0;
     97         for(i=1;i<=n;i++)
     98             if(AC::ans[pos[i]]>a1)
     99                 a1=AC::ans[pos[i]];
    100         for(i=1;i<=n;i++)
    101             if(AC::ans[pos[i]]==a1)
    102                 anss++;
    103         printf("%d
    ",a1);
    104         for(i=1;i<=n;i++)
    105             if(AC::ans[pos[i]]==a1)
    106                 printf("%s
    ",s[i]);
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    [c++]基类对象作为函数參数(赋值兼容规则)
    easyui datagird 总计栏
    openssl之BIO系列之25---结束语
    具体解释Hibernate中的二级缓存
    记真实自己,炫精彩人生---《爱记》app使用体验
    设置-安全-手机加密功能解说
    Linux下Redis安装
    解题报告 之 HDU5317 RGCDQ
    FireFox所支持的全部标签(持续更新ing)
    本书已出版&lt;拨云见日:基于android的内核与系统架构源代码分析 &gt;
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8810666.html
Copyright © 2011-2022 走看看