描述 Description
Hamed has recently found a string t and suddenly became quite fond of it. He spent several days trying to find all occurrences of t in other strings he had. Finally he became tired and started thinking about the following problem. Given a string s how many ways are there to extract k ≥ 1 non-overlapping substrings from it such that each of them contains string t as a substring? More formally, you need to calculate the number of ways to choose two sequences a1, a2, …, ak and b1, b2, …, bk satisfying the following requirements:
k ≥ 1
\[\forall i(1 \leq i \leq k) \ 1 \leq a_i,b_i \leq |s|\]
\[\forall i(1 \leq i \leq k) \ b_i \geq a_i\]
\[\forall i(2 \leq i \leq k) \ a_i > b_{i-1}\]
\[\forall i(1 \leq i \leq k)\] t is a substring of string saisai + 1… sbi (string s is considered as 1-indexed).
As the number of ways can be rather large print it modulo 109 + 7.
输入格式 InputFormat
Input consists of two lines containing strings s and t (1 ≤ |s|, |t| ≤ 105). Each string consists of lowercase Latin letters.
输出格式 OutputFormat
Print the answer in a single line.
样例输入 SampleInput
welcometoroundtwohundredandeightytwo
d
样例输出 SampleOutput
274201
代码 Code
kmp 预处理出 s[i] 结尾的字符串是否是 t,f[i] 表示前 i 个字符、最后一个字符串以 s[i] 结尾的方案数,g[i] 表示前 i 个字符的方案数(即 f[i] 前缀和),sum[i] 表示 g[i] 前缀和。
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=100005;
const int mod=1000000007;
int i,j,n,m,l,r,k,z,y,x;
char s[maxn],t[maxn];
bool b[maxn];
int pre[maxn],f[maxn],g[maxn],sum[maxn];
inline void kmp()
{
int i,j,k;
memset(b,false,sizeof(b));
pre[1]=j=0;
for (i=2;i<=m;i++)
{
while (j>0 && t[j+1]!=t[i]) j=pre[j];
if (t[j+1]==t[i]) j++;
pre[i]=j;
}
j=0;
for (i=1;i<=n;i++)
{
while (j>0 && t[j+1]!=s[i]) j=pre[j];
if (t[j+1]==s[i]) j++;
if (j==m) b[i]=true;
}
}
int main()
{
scanf("%s%s",s+1,t+1);
n=strlen(s+1);m=strlen(t+1);
kmp();
for (i=1;i<=n;i++)
{
if (!b[i])
{
f[i]=f[i-1];
g[i]=(g[i-1]+f[i])%mod;
sum[i]=(sum[i-1]+g[i])%mod;
}
else
{
f[i]=sum[i-m]+i-m+1;
g[i]=(g[i-1]+f[i])%mod;
sum[i]=(sum[i-1]+g[i])%mod;
}
}
printf("%d\n",g[n]);
return 0;
}