题目链接:点击打开链接
题目大意:给你一个字符串和一个有两个意思的字符串,问前一个字符串能有多少种不同的意思。
解题思路:用kmp找重复,再用dp计算数量方程也很简单dp[i]=dp[i-1]+dp[i-len2](如果i是匹配的最后一个位置)
代码:
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
#include "bitset"
using namespace std;
const int mod = 1000000007;
char str1[100001], str2[100001];
int vis[100001], dp[100001];
void GetFail(char *P, int *f)
{
int m = strlen(P);
f[0] = 0;
f[1] = 0;
for (int i = 1; i < m; i++)
{
int j = f[i];
while (j && P[i] != P[j]) j = f[j];
f[i + 1] = (P[i] == P[j] ? j + 1 : 0);
}
}
int Find(char *T, char *P, int *f)
{
int n = strlen(T), m = strlen(P);
GetFail(P, f);
int j = 0;
for (int i = 0; i < n; i++)
{
while (j && P[j] != T[i]) j = f[j];
if (P[j] == T[i]) j++;
if (j == m) vis[i + 1] = 1;
}
return -1;
}
int f[100001];
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--)
{
memset(vis, 0, sizeof(vis));
scanf(" %s %s", str1+1, str2+1);
int len1 = strlen(str1+1), len2 = strlen(str2+1);
printf("Case #%d: ", ++cas);
Find(str1 + 1, str2 + 1, f);
long long ans = 0;
dp[0] = 1;
for (int i = 1;i <= len1;i++)
{
if (vis[i])
dp[i] = (dp[i - len2] + dp[i - 1]) % mod;
else
dp[i] = dp[i - 1];
}
printf("%lld\n", dp[len1]);
}
return 0;
}
kmp模版:
#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<ctime>
#include "cstdio"
#include "string"
#include "string.h"
#include "map"
#include "bitset"
using namespace std;
const int mod = 1000000007;
const int MAXN = 100001;
struct Kmp
{
char str1[MAXN], str2[MAXN];
int vis_end[MAXN], vis_start[MAXN];//vis_end
int dp[MAXN];
int len1, len2;
void init()
{
memset(vis_end, 0, sizeof(vis_end));
memset(vis_start, 0, sizeof(vis_start));
scanf(" %s %s", str1 + 1, str2 + 1);
len1 = strlen(str1 + 1), len2 = strlen(str2 + 1);
}
void GetFail(char *P, int *f)
{
int m = strlen(P);
f[0] = 0;
f[1] = 0;
for (int i = 1; i < m; i++)
{
int j = f[i];
while (j && P[i] != P[j]) j = f[j];
f[i + 1] = (P[i] == P[j] ? j + 1 : 0);
}
}
int Find(char *T, char *P, int *f)
{
int n = strlen(T), m = strlen(P);
GetFail(P, f);
int j = 0;
for (int i = 0; i < n; i++)
{
while (j && P[j] != T[i]) j = f[j];
if (P[j] == T[i]) j++;
if (j == m)
{
vis_end[i + 1] = 1;
vis_start[i + 1 - m] = 1;
}
}
return -1;
}
}kmp;
int f[100001];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
kmp.init();
kmp.Find(kmp.str1 + 1, kmp.str2 + 1, f);
}
return 0;
}