• AC自动机(Keywords Search)


    题目链接:https://cn.vjudge.net/contest/280743#problem/A

    题目大意:首先给你T组测试样例,然后给你n个字符串,最后再给你一个模式串,然后问你这一些字符串中是模式串的子串的有多少个?

    具体思路:AC自动机模板题,先说一下各个数组的作用吧,ch数组是字典树中的数组,val也是字典树中的数组,储存的是从根节点到当前这个节点是不是有字符串。fail和last就是AC自动机中的数组了,fail数组的作用就是从根节点到当的节点形成的字符串的后缀是一个新的路径的前缀,能够在匹配失败的时候,通过指针的跳动来节省时间。last数组的作用就是在求和的时候方便记录,如果当前节点有字符串的话,直接通过指针的跳动能够避免当前节点没有字符串的情况。

    AC代码:

      1 #include<iostream>
      2 #include<stack>
      3 #include<stdio.h>
      4 #include<cstring>
      5 #include<string>
      6 #include<cmath>
      7 #include<queue>
      8 #include<algorithm>
      9 using namespace std;
     10 # define ll long long
     11 const int maxn = 2e5+50000;
     12 const int maxm = 1e6+100;
     13 char str[maxm];
     14 int tot,ch[maxn][30],val[maxn];
     15 int fail[maxn],last[maxn];
     16 void add()
     17 {
     18     int p=0;
     19     int len=strlen(str);
     20     for(int i=0; i<len; i++)
     21     {
     22         int u=str[i]-'a';
     23         if(!ch[p][u])
     24             ch[p][u]=++tot;
     25         p=ch[p][u];
     26     }
     27     val[p]++;
     28 }
     29 void getfail()
     30 {
     31     queue<int>q;
     32     for(int i=0; i<26; i++)
     33     {
     34         if(ch[0][i])
     35             q.push(ch[0][i]);
     36     }
     37     while(!q.empty())
     38     {
     39         int top=q.front();
     40         q.pop();
     41         for(int i=0; i<26; i++)
     42         {
     43             int u=ch[top][i];
     44             if(u==0)
     45                 continue;
     46                 q.push(u);
     47             int v=fail[top];
     48             while(v&&ch[v][i]==0)
     49                 v=fail[v];
     50             fail[u]=ch[v][i];
     51             last[u]=val[fail[u]] ? fail[u] : last[fail[u]];
     52         }
     53     }
     54 }
     55 int cal(int t)
     56 {
     57     int ans=0;
     58     while(t)
     59     {
     60         ans+=val[t];
     61          val[t]=0;
     62         t=last[t];
     63     }
     64     return ans;
     65 }
     66 int getans()
     67 {
     68     int ans=0;
     69     int len=strlen(str);
     70     int p=0;
     71     for(int i=0; i<len; i++)
     72     {
     73       int u=str[i]-'a';
     74         while(p&&ch[p][u]==0)
     75             p=fail[p];
     76             p=ch[p][u];
     77         if(val[p])
     78             ans+=cal(p);
     79         else if(fail[p])
     80             ans+=cal(fail[p]);
     81     }
     82     return ans;
     83 }
     84 void init()
     85 {
     86     for(int i=0; i<tot; i++)
     87     {
     88         fail[i]=0,last[i]=0,val[i]=0;
     89         for(int j=0; j<30; j++)
     90         {
     91             ch[i][j]=0;
     92         }
     93     }
     94     tot=0;
     95 }
     96 int main()
     97 {
     98     int T;
     99     scanf("%d",&T);
    100     while(T--)
    101     {
    102         init();
    103         int n;
    104         scanf("%d",&n);
    105         for(int i=1; i<=n; i++)
    106         {
    107             scanf("%s",str);
    108             add();
    109         }
    110         getfail();
    111         scanf("%s",str);
    112         int ans=getans();
    113         printf("%d
    ",ans);
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    mysql数据类型
    Hive Getting Started补充
    Hive安装
    HDFS High Availability Using the Quorum Journal Manager
    用DBContext (EF) 实现通用增删改查的REST方法
    Internet Explorer 10 administration IE10管理
    配置AD RMS及SharePoint 2013 IRM问题解决及相关资源
    SharePoint 2013 首页修改
    Status: Checked in and viewable by authorized users 出现在sharepoint 2013 home 页面
    添加AD RMS role时,提示密码不能被验证The password could not be validated
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10309605.html
Copyright © 2020-2023  润新知