Searching the String ZOJ - 3228(ac自动机)

时间:2021-03-05 05:59:50

Searching the String

 ZOJ - 3228

题意:两种查询,普通的就是ac自动机模板,另外一种要求没有发生覆盖。

处理方式是判断一下如果当前匹配到的位置(u)减去上一次匹配到的位置(ed[u])大于该字符的深度(deep[u]),就加1。

Searching the String ZOJ - 3228(ac自动机)Searching the String ZOJ - 3228(ac自动机)
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 
  5 const int maxnode=5*1e5+10;
  6 const int sigma=26;
  7 
  8 struct AC{
  9     int ch[maxnode][sigma],f[maxnode],last[maxnode];
 10     int val[maxnode],deep[maxnode];
 11     int cnt[maxnode][2];
 12     int ed[maxnode];
 13     int sz;
 14 
 15     void init(){
 16         CLR(ch[0],0);
 17         sz=1;
 18         CLR(ed,-1);
 19         CLR(val,0);
 20         CLR(cnt,0);
 21     }
 22 
 23     int idx(char c){return c-'a';}
 24 
 25     int inser(char *s){
 26         int u=0,n=strlen(s);
 27         for(int i=0;i<n;i++){
 28             int c=idx(s[i]);
 29             if(!ch[u][c]){
 30                 CLR(ch[sz],0);
 31                 deep[sz]=i+1;   //
 32                 ch[u][c]=sz++;
 33             }
 34             u=ch[u][c];
 35         }
 36         val[u]=1;
 37         return u;
 38     }
 39 
 40     void getfail(){
 41         queue<int> q;
 42         f[0]=0;
 43         last[0]=0;
 44         for(int c=0;c<sigma;c++){
 45             int u=ch[0][c];
 46             if(u){
 47                 f[u]=0;
 48                 last[u]=0;
 49                 q.push(u);
 50             }
 51         }
 52         while(!q.empty()){
 53             int r=q.front();
 54             q.pop();
 55             for(int c=0;c<sigma;c++){
 56                 int u=ch[r][c];
 57                 if(!u) continue;
 58                 q.push(u);
 59                 int v=f[r];
 60                 while(v&&!ch[v][c]) v=f[v];
 61                 f[u]=ch[v][c];
 62                 last[u]=val[f[u]]?f[u]:last[f[u]];
 63             }
 64         }
 65     }
 66     void print(int u,int i){
 67         if(val[u]){
 68             cnt[u][0]++;
 69             if(i-ed[u]>=deep[u]){
 70                 cnt[u][1]++;
 71                 ed[u]=i;
 72             }
 73             print(last[u],i);
 74         }
 75     }
 76     void query(char *s){
 77         int u=0,n=strlen(s);
 78         for(int i=0;i<n;i++){
 79             int c=idx(s[i]);
 80             while(u&&!ch[u][c]) u=f[u];
 81             u=ch[u][c];
 82             if(val[u]) print(u,i);
 83             else if(last[u]) print(last[u],i);
 84         }
 85     }
 86 };
 87 const int maxn=1e5+10;
 88 int pos[maxn],c[maxn];
 89 char s[maxn],p[10];
 90 AC ac;
 91 int main(){
 92     int kase=0;
 93     while(scanf("%s",s)!=EOF){
 94         ac.init();
 95         printf("Case %d\n",++kase);
 96         int n;
 97         scanf("%d",&n);
 98         for(int i=0;i<n;i++){
 99             scanf("%d%s",&c[i],p);
100             pos[i]=ac.inser(p);
101         }
102         ac.getfail();
103         ac.query(s);
104         for(int i=0;i<n;i++){
105             printf("%d\n",ac.cnt[pos[i]][c[i]]);
106         }
107         puts("");
108     }
109     return 0;
110 }
View Code