zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Balanced Binary Tree
    Convert Sorted List to Binary Search Tree
    Convert Sorted Array to Binary Search Tree
    Binary Tree Zigzag Level Order Traversal
    Validate Binary Search Tree
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Maximum Depth of Binary Tree
    如何把U盘的两个盘或者多个盘合成一个
    bugku 想蹭网先解开密码
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10309605.html
Copyright © 2011-2022 走看看