题意:给一个文本串和一个模式串,模式串能被*代替,问文本串有几种表达方式
思路,首先用KMP把模式串找出来,在其末尾用vis标记,然后DP,若i被标记,则dp[i]=dp[i-1]+dp[i-m],否则dp[i]=dp[i-1]。
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
char a[maxn],b[maxn];
int Next[maxn];
int n,m;
bool vis[maxn];
long long dp[maxn];
void kmp(){
memset(Next,0,sizeof(Next));
Next[0]=-1;
int k=-1;
int j=0;
while(j<m-1){
if(k==-1 || b[k]==b[j]){
k++;
j++;
Next[j]=k;
}else{
k=Next[k];
}
}
int i=0;
k=0;
memset(vis,false,sizeof(vis));
while(i<n){
if(k==-1 || a[i]==b[k]){
i++;
k++;
}else{
k=Next[k];
}
if(k==m){
vis[i-1]=true;
i-=m-1;//找到一个,令i跳转到i-m+1个字母上
}
}
}
int main(){
freopen("in.txt","r",stdin);
int t;
cin>>t;
for(int ca=1;ca<=t;ca++){
printf("Case #%d: ",ca);
scanf("%s%s",&a,&b);
n=strlen(a);
m=strlen(b);
kmp();
memset(dp,0,sizeof(dp));
dp[0]=1;
if(vis[0]) dp[0]+=1; //m=1,a[0]即为模式串时
for(int i=1;i<n;i++){
dp[i]=dp[i-1];
if(vis[i]){
if(i-m<0) dp[i]+=dp[0];//从第一个开始匹配时,i-m会等于-1
else dp[i]+=dp[i-m];
}
dp[i]%=mod;
}
cout<<dp[n-1]<<endl;
}
}