题意:t组询问,每次给出串(a,b),串(a)中与(b)相等的字串可以替换为(*),问a可以变为多少种字符串。
KMP+DP,从前往后(dp)串(a)的每一个位置,设枚举到(i),如果(a[i-len(b) ... i]==b),那么我们就可以选择是否将这个字串替换,答案就等于不替换的方案数((f[i-1]))加替换的方案数((f[i-len(b)]))。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+100,P=1e9+7;
int n,m,t,nex[maxn],ok[maxn],k,f[maxn];
char a[maxn],b[maxn];
void getnex(){
nex[1]=0,k=0;
for(int i=2;i<=n;i++){
while(k>0&&b[k+1]!=b[i])
k=nex[k];
if(b[k+1]==b[i])
k++;
nex[i]=k;
}
}
int main(){
scanf("%d",&t);
for(int o=1;o<=t;o++){
scanf("%s%s",a+1,b+1);
n=strlen(a+1),m=strlen(b+1);
memset(ok,0,sizeof(ok));
getnex();
for(int i=0,j=0;i<=n;i++){
if(j>0&&a[i+1]!=b[j+1])
j=nex[j];
if(a[i+1]==b[j+1])
j++;
if(j==m){
ok[i+1]=1;
j=nex[j];
}
}
f[0]=1;
for(int i=1;i<=n;i++){
f[i]=f[i-1];
if(ok[i])
f[i]+=f[i-m],f[i]%=P;
//这里可以让f[i]+=1,前面f[0]=0,
//后面输出f[n]+1,不知道为什么能对?
}
printf("Case #%d: %d
",o,f[n]);
}
}