先用KMP重叠匹配求出各个匹配成功的尾串位置。然后利用DP去求,那转移方程应该是等于
上一个状态 (无法匹配新尾巴)
上一个状态 + 以本次匹配起点为结尾的状态(就是说有了新的位置) + 1 (单单一个新串) (匹配成功)
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 7; const int mod = 1000000007; long long dp[maxn]; char str1[maxn], str2[maxn]; bool flag[maxn]; /* * nex[] 的含义:x[i-nex[i]...i-1]=x[0...nex[i]-1] * nex[i] 为满足 x[i-z...i-1]=x[0...z-1] 的最大 z 值(就是 x 的自身匹配) */ void kmp_pre(char x[], int m, int kmpNext[]) { int i, j; j = kmpNext[0] = - 1; i = 0; while(i < m) { while( - 1 != j && x[i] != x[j]) j = kmpNext[j]; kmpNext[++i] = ++j; } } /* * kmpNext[i] 的意思:nex'[i]=nex[nex[...[nex[i]]]](直到 nex'[i]<0 或者 x[nex'[i]]!=x[i]) * 这样的预处理可以快一些 */ void preKMP(char x[], int m, int kmpNext[]) { int i, j; j = kmpNext[0] = - 1; i = 0; while(i < m) { while( - 1 != j && x[i] != x[j]) j = kmpNext[j]; if(x[++i] == x[++j]) kmpNext[i] = kmpNext[j]; else kmpNext[i] = j; } } /* * 返回 x 在 y 中出现的次数,可以重叠 */ int nex[10010]; int KMP_Count(char x[], int m, char y[], int n) { //x 是模式串,y 是主串 int i, j; int ans = 0; //preKMP(x,m,nex); kmp_pre(x, m, nex); i = j = 0; while(i < n) { while( - 1 != j && y[i] != x[j]) j = nex[j]; i++; j++; if(j >= m) { ans++; flag[i] = 1; j = nex[j]; } } return ans; } int main() { int T, ncase = 1; scanf("%d", &T); while(T --) { scanf("%s%s", str1, str2); int l1 = strlen(str1); int l2 = strlen(str2); memset(flag, 0, sizeof(flag)); memset(dp, 0, sizeof(dp)); KMP_Count(str2, l2, str1, l1); for(int i = l2; i <= l1; i ++) dp[i] = flag[i] ? (dp[i - 1] + dp[i - l2] + 1) % mod : dp[i - 1]; printf("Case #%d: %lld ",ncase++,(dp[l1] + 1)%mod); } return 0; }