HDU 3336 Count the string(KMP+Next数组递推)
2015-08-19 20:15
211 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336
题目大意:给定一个字符串,求所有前缀串在母串中匹配的数量,包含前缀串本身。
注意一个坑点,虽然没有被坑到。比如aaaaaa,前缀串aa的匹配数目为4个。包括aaaaaa, aaaaaa, aaaaaa, aaaaaa
必须保证与前缀串匹配的串与之不交叉。
先求KMP的next数组,然后遍历所有的前缀串,判断这个前缀串中有几个与匹配数。获得的数目+前缀串总数就可以了。
为了更好地说明问题,我们举abcabcab为例。首先result+=8(所有前缀串(包括本身));
ab 无
abc 无
abca 匹配串为a,匹配数为1 result++
abcab 匹配串为ab,匹配数为1 result++
abc abc 匹配串为abc,匹配数为1 result++
abcabca匹配串为abca, 但是不满足不交叉,即next[i] * 2 > i, 那么就继续对abca进行匹配,得到匹配串a。
所以有abcabca,因为a1=a2, a2=a3,故a1=a3,这个自己感觉一下就可以了。至于中间的a之前已经作为后缀子串计算过了。匹配数为1, result++;
abcabcab 匹配串为ab, 匹配数为1, result++
这样可以枚举出所有的情况。不重复也不缺少,理由是每次枚举的后缀子串的最后一位的下标都不一样。
核心部分还是在next[i] * 2 > i时,应该计算出所有匹配的前缀后缀不交叉的匹配数目。
这个理解还得再看看这个例子:aaaa,匹配串为aaa, 但是next[i] * 2 > i(交叉了),所以取aaa继续操作,得到aa。aa与原串比不超过一半,所以aa aa是一组。但是因为aa的next[2]
> 0(很关键),所以继续操作,得到a,a与原串比显然不超过一半,所以aaaa也是一组。所以问题还是在于要一直处理到next <= 0为止。
不懂提问吧,贴代码来,网上的dp没看明白啥意思,不过自己做出来感觉挺好,也挺快。
题目大意:给定一个字符串,求所有前缀串在母串中匹配的数量,包含前缀串本身。
注意一个坑点,虽然没有被坑到。比如aaaaaa,前缀串aa的匹配数目为4个。包括aaaaaa, aaaaaa, aaaaaa, aaaaaa
必须保证与前缀串匹配的串与之不交叉。
先求KMP的next数组,然后遍历所有的前缀串,判断这个前缀串中有几个与匹配数。获得的数目+前缀串总数就可以了。
为了更好地说明问题,我们举abcabcab为例。首先result+=8(所有前缀串(包括本身));
ab 无
abc 无
abca 匹配串为a,匹配数为1 result++
abcab 匹配串为ab,匹配数为1 result++
abc abc 匹配串为abc,匹配数为1 result++
abcabca匹配串为abca, 但是不满足不交叉,即next[i] * 2 > i, 那么就继续对abca进行匹配,得到匹配串a。
所以有abcabca,因为a1=a2, a2=a3,故a1=a3,这个自己感觉一下就可以了。至于中间的a之前已经作为后缀子串计算过了。匹配数为1, result++;
abcabcab 匹配串为ab, 匹配数为1, result++
这样可以枚举出所有的情况。不重复也不缺少,理由是每次枚举的后缀子串的最后一位的下标都不一样。
核心部分还是在next[i] * 2 > i时,应该计算出所有匹配的前缀后缀不交叉的匹配数目。
这个理解还得再看看这个例子:aaaa,匹配串为aaa, 但是next[i] * 2 > i(交叉了),所以取aaa继续操作,得到aa。aa与原串比不超过一半,所以aa aa是一组。但是因为aa的next[2]
> 0(很关键),所以继续操作,得到a,a与原串比显然不超过一半,所以aaaa也是一组。所以问题还是在于要一直处理到next <= 0为止。
不懂提问吧,贴代码来,网上的dp没看明白啥意思,不过自己做出来感觉挺好,也挺快。
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; char str[200005]; int Next[200005]; void getNext(int len) { int i = 0, j = -1; Next[0] = -1; while(i < len) { if(j == -1 || str[i] == str[j]) { Next[++i] = ++j; } else { j = Next[j]; } } } int main () { int n, t; scanf("%d", &t); while (t --) { scanf("%d%s", &n, str); getNext(n); int sum = n, res; for (int i = 1; i <= n; i ++) { res = Next[i]; while (res > 0) { if(res * 2 <= i) { sum = (sum % 10007 + 1) % 10007; } res = Next[res]; } } printf("%d\n", sum); } return 0; }
相关文章推荐
- HDU - 4090(暴力剪纸题目,)
- IOS-笔记9(多MVC,View间转换)
- flowplayer(5.5.2版本)的播放视频
- 逆序数的几种求法
- 杭电(hdu)2544 最短路
- MLC模式这边看过来
- ios文件管理
- 软件工程—总结
- 123
- vijos - P1739计算系数 (多项式计算 + 杨辉三角形 + 快速幂)
- leetcode 257: Binary Tree Paths
- java IO流总结
- Intent的启动和属性(action)
- codeforces 123A A. Prime Permutation(数论+构造)
- iOS -归档
- ios 控制器的生命周期
- VC++新建工程和调试
- 黑马程序员—反射
- 五大布局——表格、帧、绝对布局
- 贝叶斯决策论小结