题目链接: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 init(); 101 scanf("%d",&n); 102 for(int i=0; i<n; i++){ 103 scanf("%d %s",&type[i],str2); 104 add(i); 105 } 106 getfail(); 107 getans(); 108 printf("Case %d ",++Case); 109 for(int i=0; i<n; i++){ 110 printf("%d ",ans[node[i]][type[i]]); 111 } 112 printf(" "); 113 } 114 return 0; 115 }