Count the string HDU

来源:互联网 发布:阴阳师神龙强化数据 编辑:程序博客网 时间:2024/06/05 15:09

Count the string HDU - 3336
It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example:
s: “abab”
The prefixes are: “a”, “ab”, “aba”, “abab”
For each prefix, we can count the times it matches in s. So we can see that prefix “a” matches twice, “ab” matches twice too, “aba” matches once, and “abab” matches once. Now you are asked to calculate the sum of the match times for all the prefixes. For “abab”, it is 2 + 2 + 1 + 1 = 6.
The answer may be very large, so output the answer mod 10007.
Input
The first line is a single integer T, indicating the number of test cases.
For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters.
Output
For each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.
Sample Input
1
4
abab
Sample Output
6

这道题呢 又是 KMP next 数组 的 一个 不一样的用法,这个用法呢 不是太好理解,但是呢 也不是很难的,;-)。 先说一下 题目的大概意思:首先给你一个字符串, 然后 让你查找 该字符串 的每一个 前缀(注意 是 前缀 ,要区别 真前缀),在 字符串中的匹配 次数,然后 算出 匹配次数的累加和 , 输出即可。思考一下 如果 你 把 每一个前缀都循环一边的 话 肯定会 超时的 ,这 就要用到 next 数组啦, 先 定义一个 dp 数组, 看到 dp 大家 应该 就知道 会用 到动态规划啦,dp【i】 表示的意思是, 字符串的前 i 个 字符中, 以 第 i 个 字符 为 结尾的 前缀的 个数, 但是 不包括 自己本身,动态转移方程 为 : dp[i] = dp[next[i]] + 1; 提示 一点 这里的 next 【i】 存储的 是 , 0 -> i-1 对应字符的 匹配 数 , 而 有的 朋友 学习的 next数组 是存储的 包括 当前字符 的 匹配数, 具体 看 代码, 两种 方法的 最大区别就是 , 一个是,next【0】 = -1(该题 需要的 类型 数组), 另一种 的是 next【0】 = 0; 这 里的 动态转移方程 不是太好理解, 结合 这 对 next 数组的 理解 ,还是可以 相同的,next 数组的 所表示的意思就 是 当前 前面的 子字符串 中 与 前缀 的 匹配长度。 大家好好理解!

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;void GetNext(char *p, int *next){    int p_len = strlen(p);    int i = 0;    int j = -1;    next[0] = -1;    while(i < p_len)    {        if(j == -1 || p[i] == p[j])        {            i++;            j++;            next[i] = j;        }        else            j = next[j];    }}int main(){    int t; cin>>t;    while(t--)    {        int n;        static char p[200010];        int next[200010];        int dp[200010];        scanf("%d", &n);        scanf(" %s", p);        GetNext(p, next);        memset(dp, 0, sizeof(dp));        int ans = 0;        for(int i = 1; i <= n; i++)        {            dp[i] = dp[next[i]] + 1;            ans = (ans + dp[i]) % 10007;        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击