zoukankan      html  css  js  c++  java
  • KMP---Count the string

    题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110060#problem/A

    Description

    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.
    adfsa

    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 

    题意: 给一个字符串,求这个字符串的所有前缀在字符串中出现的次数和。

    思路: 使用next[]跳转表,已经有了next数组,next[i]=k表示最大的j使得0~k-1==i-k+1~i,因此,对于样例abab,则有

           0   1   2   3

    s[]  a    b   a   b

    p[]  0    0   1   2

    对于4个前缀:

    a

    ab

    aba

    abab

    设dp[i]表示子串s[0~i]共含有以s[i]为结尾的前缀的数目,则以s[i]结尾的前缀数就是自己本身加上以s[p[i]]结尾的前缀数,也就是例如i=2

    则有:p[i]=1,dp[i]=dp[p[i]-1]+1 ;

    a

    aba这两个前缀,其中a就是s[p[i]]结尾的前缀。

    本题代码:

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    char s[200005];
    int  p[200005];
    int  dp[200005];
    int n;
    
    int next_()
    {
        int k=0;
        int sum=1;
        int len=strlen(s);
        p[0]=0;
        dp[0]=1;
        for(int i=1;i<len;i++)
        {
            while(k>0&&s[k]!=s[i])
                k=p[k-1];
            if(s[k]==s[i])
                k++;
            if(k>0) dp[i]=(dp[k-1]+1)%10007;
            else    dp[i]=1;
            sum=(sum+dp[i])%10007;
            p[i]=k;
        }
        return sum;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%s",&n,s);
            printf("%d
    ",next_());
        }
        return 0;
    }
  • 相关阅读:
    软件架构学习小结
    Azure编程笔记(1):序列化复杂类型的TableEntity字段
    目标检測的图像特征提取之(一)HOG特征
    Gmail POP3设置
    MP3的频率、比特率、码率与音质的关系
    Oracle Dataguard 介绍
    【Github教程】史上最全github用法:github入门到精通
    Xcode6在10.9.4上面crash解决
    OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)
    调用ShellExecute所须要头文件
  • 原文地址:https://www.cnblogs.com/chen9510/p/5308134.html
Copyright © 2011-2022 走看看