problem:
http://codeforces.com/problemset/problem/494/B
给你两个字符串。s 和 t , 长度不超过1e5
问有多少a 1, a2, ..., ak 和 b1, b2, ..., bk 序列对满足以下:
- k ≥ 1
t is a substring of string saisai + 1... sbi (string s is considered as 1-indexed).
input
ababa aba
output
5
input
welcometoroundtwohundredandeightytwo d
output
274201
input
ddd d
output
12
think:
1. 首先要解读题意。有点抽象。这个看一下样例就好了。
第一个样例:
1,3
1,4
1,5
2,5
3,5
第三个样例:
1,1
1,2
1,3
2,2
2,3
3,3
12,12
12,13
13,13
13,23
23,23
123,123
比如13,23表示 a = 1,3 b = 2,3
2,2
2,3
3,3
12,12
12,13
13,13
13,23
23,23
123,123
比如13,23表示 a = 1,3 b = 2,3
2. 预处理pre数组,表示第i个字符,前面,最靠后的可以和他sub的位置。
3. 前 j 位是一起的。。。然后从 j+1 到 i 组成一个新的(因为他要求 ai > b(i-1))
前j位是dp[j]
从j+1到i是 pri[i] - j 。 因为新加进来的左区间是是 j+1 ~ pri[i] 右区间是 i
然后把这两块乘起来,dp[j] * (pre[i]-j)
然后枚举所有可能的 j 然后展开一下,就O(n)了,
然后加上pri[i], 表示数组只有 1 个,没有 j
从j+1到i是 pri[i] - j 。 因为新加进来的左区间是是 j+1 ~ pri[i] 右区间是 i
然后把这两块乘起来,dp[j] * (pre[i]-j)
然后枚举所有可能的 j 然后展开一下,就O(n)了,
然后加上pri[i], 表示数组只有 1 个,没有 j
综上
dp[i] = sum(dp[j] * (pre[i] - j), j < pre[i]) + pre[i] = sum(dp[j]) * pre[i] - sum(dp[j] * j) + pre[i] = sum1[pre[i]-1] * pre[i] - sum2[pre[i] - 1] + pre[i]
sum1[i] = sum[i-1] + dp[i]
sum2[j] = sum[i-1] + dp[i] * i
code:
const int mod = 1000000007;
const int N = 100100;
char a[N];
char b[N];
int pre[N];
int dp[N];
int sum1[N];
int sum2[N];
int fail[N];
int match[N];
int nb, na;
void get_fail(int *fail, const char *p){
fail[0] = -1;
for(int i = 1; p[i]; ++i){
int j = fail[i-1];
while(j != -1 && p[j+1] != p[i]) j = fail[j];
fail[i] = (p[i] == p[j+1] ? j + 1 : -1);
}
}
void kmp(const char *a, const char *b, const int na, const int nb){
match[0] = (a[0] == b[0] ? 0 : -1);
if(match[0] == nb - 1) pre[1] = 1;
else pre[1] = 0;
for(int i = 1; a[i]; ++i){
int j = match[i-1];
if(j == nb - 1) j = fail[j];
while(j != -1 && a[i] != b[j+1]) j = fail[j];
match[i] = (a[i] == b[j+1] ? j + 1 : -1);
if(match[i] == nb - 1) pre[i + 1] = i + 2 - nb;
else pre[i + 1] = pre[i];
}
}
int main(){
scanf("%s%s", a, b);
int na = strlen(a);
int nb = strlen(b);
get_fail(fail, b);
kmp(a, b, na, nb);
int ans = 0;
for(int i = 1; i <= na; ++i) if(pre[i] > 0){
dp[i] = (LL)sum1[pre[i]-1] * pre[i] % mod;
dp[i] = (dp[i] - sum2[pre[i]-1] + mod) % mod;
dp[i] = (dp[i] + pre[i]) % mod;
ans = (ans + dp[i]) % mod;
sum1[i] = (sum1[i-1] + dp[i]) % mod;
sum2[i] = (sum2[i-1] + (LL)dp[i] * i % mod) % mod;
}
printf("%d\n", ans);
return 0;
}