对于这个问题,显然可以进行DP:
令dp[i]表示到i结尾的字符串可以表示的不同含义数,那么考虑两种转移:
末尾不替换含义:dp[i - 1]
末尾替换含义:dp[i - |B|] (A.substr(i - |B| + 1,|B|) = B)
那么对于末尾替换含义的转移,需要快速判断B能不能和当前位置的后缀匹配,kmp或者hash判断即可。
复杂度:O(N)
ACcode:
#include <bits/stdc++.h>
#define maxn 100100
#define mod 1000000007
int mynext[maxn];
char t[maxn],s[maxn];
int dp[maxn];
int is_match[maxn];
void get_next(char s[]){
int i,j,len=strlen(s);
j=mynext[0]=-1;
i=0;
while(i<len){
while(-1!=j&&s[i]!=s[j])j=mynext[j];
mynext[++i]=++j;
}
}
int main(){
int loop,cnt=1;
scanf("%d",&loop);
while(loop--){
scanf("%s%s",t,s);
get_next(s);
int len=strlen(t);
int m=strlen(s);
for(int i=0;i<=len;++i)dp[i]=1,is_match[i]=0;
for(int i=0,j=0;i<len;++i){
while(j&&s[j]!=t[i])j=mynext[j];
if(s[j]==t[i])j++;
if(j==m)is_match[i]=1;
}
for(int i=1;i<=len;++i){
dp[i]=dp[i-1];
if(is_match[i-1])
dp[i]=(dp[i-m]+dp[i])%mod;
}
printf("Case #%d: %d\n",cnt++,dp[len]);
}
return 0;
}