http://www.elijahqi.win/archives/487
B. Obsessive String
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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
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.
Input
Input consists of two lines containing strings s and t (1 ≤ |s|, |t| ≤ 105). Each string consists of lowercase Latin letters.
Output
Print the answer in a single line.
Examples
Input
ababa
aba
Output
5
Input
welcometoroundtwohundredandeightytwo
d
Output
274201
Input
ddd
d
Output
12
这题今晚写的有点神志不清了,明天还得搭乘航班飞往胡志明,先留坑,明早填坑的。
满足以下条件
1、集合中的所有串都是s的子串,且互不重叠 2、集合中的所有串都含有子串t。
设串s长度为n,串t长度为m,我们首先用kmp在s中匹配t,匹配成功的位置我们打下标记flag[i]=1(s[i-m+1…i]=t[1..m]).
设f[i]表示在s中以i结尾的集合数目,sum1[i]为fp[1..i]得前缀和,sum2[i]为sum1[1..i]得前缀和。如果flag[i]为0,则f[i]=f[i-1]。如果flag[i]为1,则dp[i]=i-m+1+sum2[i-m]。证明:若flag[i]=1,说明s[i-m+1…i]=t[1..m],那么sj..i都含有子串t,如果集合中只有一个串的话,一共有i-m+1种,如果在集合中有两个以上匹配的,那么假设我们选择其中一个串,能和他匹配的串,因为不能重叠,所以是f[1]+f[2]+..+f[j-1]即sum1[j-1],那么所有的可能就是sum1[1]+sum1[2]…+sum1[i-m],即sum2[i-m]。所以f[i]=i-m+1+sum2[i-m]
解释一下这个推导过程,大概就是多个完全匹配的时候,那么当前这个,同若只有一个的时候i-m+1
然后前面每个完全匹配的就由sum2提供,在纸上画一下 假设一个s串,然后t在其中有三个匹配的,然后就可以明白了
http://blog.youkuaiyun.com/icefox_zhx/article/details/76038942
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define N 100100
bool flag[N];
int f[N],sum1[N],sum2[N],next[N];
char s[N],t[N];
long long ans;
int main(){
freopen("cf494b.in","r",stdin);
// freopen("cf494b.out","w",stdout);
scanf("%s%s",s+1,t);
int i=0,j=-1,n=strlen(t);next[0]=-1;
while (i<n){
if (j==-1||t[i]==t[j]){
++i;++j;next[i]=j;
}else j=next[j];
}
for (int i=n;i>=1;--i) t[i]=t[i-1];
int m=strlen(s+1);int k=0;
for (int i=1;i<=m;++i){
while (k&&s[i]!=t[k+1]) k=next[k];
if (t[k+1]==s[i])++k;
if (k==n) flag[i]=true;
}
for (int i=1;i<=m;++i){
if (flag[i]){
(f[i]=i-n+1+sum2[i-n])%=mod;
}else f[i]=f[i-1];
sum1[i]=(sum1[i-1]+f[i])%mod;
sum2[i]=(sum2[i-1]+sum1[i])%mod;
}
for (int i=1;i<=m;++i) (ans+=f[i])%=mod;
printf("%d",ans);
return 0;
}