分析:
每次给出两个字符串A和B,B可以被替换成*,在A中查找B,每一个B都可以进行替换,求一共能把A替换成多少种字符串。题解:
因为A字符串的长度为100000,所以答案最多会有2的100000这么多种,直接KMP会Bomb,ShaKaLaKa,因此需要用DP来做:DP[i]表示到第i个结尾的字符串可以表示的不同含义数,每次DP转移需要用KMP判断一下:
如果到第i个结尾的字符串的后缀可以与B匹配,那么DP[i] = DP[i - |B|] (此时,(A.substr(i - |B| + 1, |B|) = B) );
如果不能匹配,那么DP[i] = DP[i - 1]
标程:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
const int MOD = 1000000007;
int T;
char a[N], b[N];
int n, m, jump[N];
int dp[N];
int main()
{
scanf("%d", &T);
int cas = 0;
while (T--)
{
scanf("%s%s", a + 1, b + 1);
n = strlen(a + 1); m = strlen(b + 1);
int j = 0;
for (int i = 2; i <= m; i++) //jump数组相当于Next数组,先预处理一遍。
{
while (j && b[i] != b[j + 1])
j = jump[j];
if (b[i] == b[j + 1])
j++;
jump[i] = j;
}
j = 0;
dp[0] = 1;
for (int i = 1; i <= n; i++)
{
while (j && a[i] != b[j + 1]) //匹配a的后缀与b
j = jump[j];
if (a[i] == b[j + 1])
j++;
dp[i] = dp[i - 1];//匹配不完成:DP[i] = DP[i - 1]
if (j == m) //匹配完成一次后:DP[i] = DP[i - |B|]
{
dp[i] = (dp[i] + dp[i - m]) % MOD;
j = jump[j];
}
}
printf("Case #%d: %d\n", ++cas, dp[n]);
}
return 0;
}