D - Searching the String (AC自动机)

Posted letlifestop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D - Searching the String (AC自动机)相关的知识,希望对你有一定的参考价值。

题目链接:https://cn.vjudge.net/contest/281961#problem/D

题目大意:给你一个模式串,然后给你多个匹配串,匹配串的类型是包括可以覆盖的以及不可覆盖的。

具体思路:对于可以覆盖的字符串,我们就按照以前的方法来就行了,对于不可以覆盖的字符串,我们通过两个数组,一个是last和pos数组,对于不可覆盖的, 当前字符位置 - last[当前节点] <= pos[当前节点]。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 str1[maxn],str2[maxn];
 14 int tot,ch[maxn][30];
 15 int type[maxn],pos[maxn],node[maxn],val[maxn];
 16 int fail[maxn],last[maxn],ans[maxn][2];
 17 void add(int t)
 18 {
 19     int p=0;
 20     int len=strlen(str2);
 21     for(int i=0; i<len; i++)
 22     {
 23         int u=str2[i]-a;
 24         if(!ch[p][u])
 25             ch[p][u]=++tot;
 26         p=ch[p][u];
 27         pos[p]=i+1;
 28     }
 29     node[t]=p;
 30     val[p]=1;
 31 }
 32 void getfail()
 33 {
 34     queue<int>q;
 35     for(int i=0; i<26; i++)
 36     {
 37         if(ch[0][i])
 38             q.push(ch[0][i]);
 39     }
 40     while(!q.empty())
 41     {
 42         int top=q.front();
 43         q.pop();
 44         for(int i=0; i<26; i++)
 45         {
 46             int u=ch[top][i];
 47             if(u==0)
 48                 continue;
 49             q.push(u);
 50             int v=fail[top];
 51             while(v&&ch[v][i]==0)
 52                 v=fail[v];
 53             fail[u]=ch[v][i];
 54           // last[u]=val[fail[u]] ? fail[u] : last[fail[u]];
 55         }
 56     }
 57 }
 58 void cal(int t,int i)
 59 {
 60     while(t)
 61     {
 62         ans[t][0]++;
 63    //     cout<<i<<" "<<last[t]<<" "<<pos[t]<<endl;
 64         if(i-last[t]>=pos[t])ans[t][1]++,last[t]=i;
 65         t=fail[t];
 66       //  break;
 67     }
 68 }
 69 void getans()
 70 {
 71     memset(last,-1,sizeof(last));
 72     int len=strlen(str1);
 73     int p=0;
 74     for(int i=0; i<len; i++)
 75     {
 76         int u=str1[i]-a;
 77         while(p&&ch[p][u]==0)
 78             p=fail[p];
 79         p=ch[p][u];
 80         if(val[p])
 81             cal(p,i);
 82         else if(fail[p])
 83             cal(fail[p],i);
 84     }
 85 }
 86 void init(){
 87 tot=0;
 88 memset(ch,0,sizeof(ch));
 89 memset(val,0,sizeof(val));
 90 memset(fail,0,sizeof(fail));
 91 memset(last,0,sizeof(last));
 92 memset(ans,0,sizeof(ans));
 93 }
 94 int main()
 95 {
 96  //   memset(last,-1,sizeof(last));
 97     int n;
 98     int Case=0;
 99     while(~scanf("%s",str1))
100     {
101         init();
102         scanf("%d",&n);
103         for(int i=0; i<n; i++)
104         {
105             scanf("%d %s",&type[i],str2);
106             add(i);
107         }
108         getfail();
109         getans();
110         printf("Case %d
",++Case);
111         for(int i=0; i<n; i++)
112         {
113             //   cout<<node[i]<<" "<<type[i]<<endl;
114             printf("%d
",ans[node[i]][type[i]]);
115         }
116         printf("
");
117     }
118     return 0;
119 }

 

以上是关于D - Searching the String (AC自动机)的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ - 3228 Searching the String (AC自己主动机)

ZOJ3228 Searching the String (AC自动机)

ZOJ3228 Searching the String(AC自动机)

ZOJ 3228 Searching the String (AC自己主动机)

ZOJ Searching the String(match指针暴力跳fail)

Searching the String ZOJ - 3228 AC自动机查询升级版