zoukankan      html  css  js  c++  java
  • hdu 3336 Count the String

    Count the string

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 5   Accepted Submission(s) : 3

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

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

    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数组,next[i]=j表示最大的j使得0~j==i-j~i,因此,对于样例abab,则有

           0   1   2   3

    b[]  a    b   a   b

    p[]  -1  -1  0   1

    对于4个前缀:

    a

    ab

    aba

    abab

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

    则有:

    a

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


    View Code
     1 #include <iostream>
     2 #include <stdio.h>
     3 using namespace std;
     4 
     5 int dp[200005];
     6 char b[200005];
     7 int p[200005];
     8 int n;
     9 
    10 int find()
    11 {
    12     int ans=1;
    13     int i,j;
    14     dp[0]=1;
    15     j=-1;
    16     p[0]=-1;
    17     for(i=1;i<n;i++)
    18     {
    19         while(j>=0 && b[j+1]!=b[i]) j=p[j];
    20         if(b[j+1]==b[i]) j++;
    21         if(j>=0) dp[i]=(dp[j]+1)%10007;        // 出去这两行就是原来简单的KMP 就pre数组。
    22         else  dp[i]=1;                            //
    23         p[i]=j;
    24         ans=(ans+dp[i])%10007;
    25     }
    26     return ans;
    27 }
    28 
    29 int main()
    30 {
    31     int i,j,t;
    32     scanf("%d",&t);
    33     while(t--)
    34     {
    35         scanf("%d",&n);
    36         scanf("%s",b);
    37         printf("%d\n",find());
    38     }
    39     //system("pause");
    40     return 0;
    41 }

    对于这一题还有个比较耗时间的做法:

    1、首先确定下这个字符串的首个字母,然后从第二个开始搜起
    当遇到和首字符一样的时候,就从该字母开始和这个字符串的首
    字符开始进行比较,知道出现不一样为止,此时相同的个数就
    加到总数上。
    2、不一样的话就从和首个字符一样的位置的下一个字符开始。
    然后和1步骤差不多,就是这个字符和首个字符往后走,遇到不
    一样又重复这个步骤。。。
     
    代码如下:
    View Code
     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 using namespace std;
     5 
     6 char str[200005];
     7 
     8 int main()
     9 {
    10     int i,j,n,sum;
    11     int t;
    12     scanf("%d",&t);
    13     while(t--)
    14     {
    15         scanf("%d",&n);
    16         sum=n;
    17         sum=sum%10007;
    18         scanf("%s",str);
    19         for(i=1;i<n;i++)
    20         {
    21             if(str[i]==str[0])
    22             {
    23                 for(j=i;j<n;j++)
    24                 {
    25                     if(str[j]!=str[j-i])
    26                         break;
    27                 }
    28 
    29                 sum+=j-i;
    30                 sum=sum%10007;
    31             }
    32         }
    33         printf("%d\n",sum);
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    自定义控件(视图)2期笔记09:自定义视图之继承自ViewGroup(仿ViewPager效果案例)
    自定义控件(视图)2期笔记08:自定义控件之 9patch图说明
    TCP/IP协议原理与应用笔记10:TCP/IP协议族
    TCP/IP协议原理与应用笔记09:数据通信---封装
    TCP/IP协议原理与应用笔记08:对等层和对等实体
    TCP/IP协议原理与应用笔记07:HTTP、TCP/IP与socket区别
    TCP/IP协议原理与应用笔记06:OSI参考模型全称
    Android进阶笔记02:Android 网络请求库的比较及实战(二)
    Android进阶笔记01:Android 网络请求库的比较及实战(一)
    自定义控件(视图)2期笔记07:自定义控件之 自定义属性(开关按钮案例的优化)
  • 原文地址:https://www.cnblogs.com/shenshuyang/p/2607665.html
Copyright © 2011-2022 走看看