题意
给两个字符串a和b,b有两义性,求a一共有多少种可能的意思。
思路
首先KMP预处理出所有b是a子串的末尾位置,然后基础dp就可以了。
如果i位置是子串末尾则dp[i] = dp[i-1] + dp[i-lenb] + 1否则直接转移。
代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 1e5 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;
bool ok[maxn];
int dp[maxn];
char a[maxn], b[maxn];
void getnext(char *p, int n, int *next)
{
int i = 0, j = -1;
next[0] = j;
while (i < n)
{
while (j != -1 && p[j] != p[i])
j = next[j];
i++, j++;
if (j >= n)
next[i] = next[j-1];
else
next[i] = j;
}
}
void kmp(char *p, int n, char *s, int m)
{
int next[10005];
getnext(p, n, next);
int i = 0, j = 0;
while (i < m)
{
while (j != -1 && p[j] != s[i])
j = next[j];
i++, j++;
if (j == n)
{
ok[i-1] = 1;
j = next[j];
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d", &T);
for (int ncase = 1; ncase <= T; ncase++)
{
scanf("%s%s", a, b);
memset(ok, 0, sizeof(ok));
kmp(b, strlen(b), a, strlen(a));
memset(dp, 0, sizeof(dp));
dp[0] = ok[0];
int len = strlen(a);
int lenb = strlen(b);
for (int i = 1; i < len; i++)
{
dp[i] = dp[i-1];
if (ok[i]) dp[i] = (dp[i] + dp[i-lenb] + 1) % MOD;
}
printf("Case #%d: %d\n", ncase, dp[len-1] + 1);
}
return 0;
}