CF - 494B - 字符串预处理 + DP
来源:互联网 发布:linux 6.0语言改为中文 编辑:程序博客网 时间:2024/05/29 06:46
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
ababaaba
output
5
input
welcometoroundtwohundredandeightytwod
output
274201
input
dddd
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;}
0 0
- CF - 494B - 字符串预处理 + DP
- cf 414B DP
- cf 264b dp
- CF 573B DP
- 【DP】 cf 487B
- CF - 294B DP
- CF - 375B DP
- CF#277 (Div. 2) B.(预处理)
- CF -- 835C Star sky 【dp + 预处理】
- CodeForces 623B【预处理+DP】
- CF 154 div2 B(dp)
- CF 2 B(dp)
- CF Div2 (220) B --- dp
- CF 429B (三维dp)
- CF - 274B 树形dp
- CF - 461B 树形dp
- CF 551B 暴力+字符串
- CF 79CBeaver DP 字符串
- C#基础知识复习
- hdu1711
- jsp页面静态化技术资料收集
- 打包
- 开始并不意味着成功
- CF - 494B - 字符串预处理 + DP
- 字符编码总结
- leetcode做题总结,回溯法(N-Queens, N-QueensII,Combination SumI&II,wordbreak II, SubsetsI&II)
- php dom操作存储xml节点
- 10gen工程师谈MongoDB组合索引的优化
- 哇噻夫微商论坛开启了
- MongoDB 数据文件备份与恢复
- 安卓面试技术点之xmpp知识准备
- Python中常用的一些操作总结(未完待续)update @ 2017-1-6