HDU 3336 Count the string(KMP+Next数组递推)

来源:互联网 发布:大数据工程师压力大吗 编辑:程序博客网 时间:2024/05/22 15:28

题目链接: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没看明白啥意思,不过自己做出来感觉挺好,也挺快。

#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;}





0 0
原创粉丝点击