题目链接:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827367940

题意:(多组输入)给出一个字符串和n个模式串,模式串前的数字 0 代表可以重叠,1代表不能重叠,求每个模式串出现的次数。

题解:算是AC自动机的板子题。在query的时候需要多判断一下不能重叠的情况,用last数组记录上一个串出现的位置,比较两个模式串的距离是否小于串的长度,小于的话就跳过,否则就+1;

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 6e5+10;
 5 const int N = 30;
 6 int a[maxn],b[maxn][2],last[maxn];
 7 
 8 struct tire{
 9     int nxt[maxn][N],fail[maxn],c[maxn],end[maxn],tot,root;
10     int newNode(){
11         for(int i=0;i<26;i++) nxt[tot][i] = -1;
12         c[tot++]=0;
13         return tot-1;
14     }
15     void Init(){
16         tot = 0;
17         root = newNode();
18     }
19     void Insert(char *buf,int id){
20         int len = strlen(buf),i,u = root;
21         for(i=0;i<len;i++){
22             int x = buf[i]-'a';
23             if(nxt[u][x]==-1) nxt[u][x] = newNode();
24             c[nxt[u][x]]=c[u]+1;
25             u = nxt[u][x];
26         }
27         end[id] = u;
28     }
29     void build(){
30         queue <int> q;
31         fail[root] = root;
32         for(int i=0;i<26;i++){
33             if(nxt[root][i]==-1) nxt[root][i] = root;
34             else{
35                 fail[nxt[root][i]] = root;
36                 q.push(nxt[root][i]);
37             }
38         }
39         while(!q.empty()){
40             int now = q.front();
41             q.pop();
42             for(int i=0;i<26;i++){
43                 if(nxt[now][i]==-1) nxt[now][i] = nxt[fail[now]][i];
44                 else{
45                     fail[nxt[now][i]] = nxt[fail[now]][i];
46                     q.push(nxt[now][i]);
47                 }
48             }
49         }
50     }
51     void query(char *buf){
52         int len = strlen(buf),now = root;
53         for(int i=0;i<len;i++){
54             int x = buf[i]-'a';
55             now = nxt[now][x];
56             int tmp = now;
57             while(tmp!=root){
58                 b[tmp][0]++;
59                 if(i-last[tmp]>=c[tmp]){
60                     b[tmp][1]++;
61                     last[tmp]=i;
62                 }
63                 tmp=fail[tmp];
64             }
65         }
66     }
67 }ac;
68 
69 char s1[10];
70 char s[100100];
71 
72 int main()
73 {
74     int t=0,n;
75     while(scanf("%s",s)!=EOF){
76         t++;
77         scanf("%d",&n);
78         ac.Init();
79         for(int i=0;i<n;i++){
80             scanf("%d",&a[i]);
81             scanf("%s",s1);
82             ac.Insert(s1,i);
83         }
84         ac.build();
85         memset(last,-1,sizeof(last));
86         memset(b,0,sizeof(b));
87         ac.query(s);
88         printf("Case %d\n",t);
89         for(int i=0;i<n;i++){
90             printf("%d\n",b[ac.end[i]][a[i]]);
91         }
92         printf("\n");
93     }
94     return 0;
95 }