zoukankan      html  css  js  c++  java
  • HDU3336 Count the string —— KMP next数组

    题目链接:https://vjudge.net/problem/HDU-3336

    Count the string

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 11760    Accepted Submission(s): 5479


    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
     
    Author
    foreverlin@HNU
     
    Source
     
    Recommend
    lcy

    题解:

    求每个前缀在字符串中出现(可重叠)的次数之和。next数组的应用。

    1.求出该字符串的next数组。

    2.枚举每个位置,然后用next数组对其进行回退,且每回退一次,都有一个前缀出现了一次(next数组的特性)。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 typedef long long LL;
    14 const double eps = 1e-6;
    15 const int INF = 2e9;
    16 const LL LNF = 9e18;
    17 const int MOD = 1e9+7;
    18 const int MAXN = 2e5+10;
    19 
    20 char x[MAXN], y[MAXN];
    21 int Next[MAXN];
    22 
    23 void get_next(char x[], int m)
    24 {
    25     int i, j;
    26     j = Next[0] = -1;
    27     i = 0;
    28     while(i<m)
    29     {
    30         while(j!=-1 && x[i]!=x[j]) j = Next[j];
    31         Next[++i] = ++j;
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     int T, n;
    38     scanf("%d", &T);
    39     while(T--)
    40     {
    41         scanf("%d%s", &n, x);
    42         get_next(x, n);
    43 
    44         int sum = 0;
    45         for(int i = 1; i<=n; i++)
    46         for(int j = i; j>=1; j = Next[j])
    47             sum = (sum+1)%10007;
    48 
    49         printf("%d
    ", sum);
    50     }
    51 }
    View Code

    51Nod 1277 字符串中的最大值

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1277

    题目来源: Codility
    基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
     收藏
     关注
    一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd。
    给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值。
    例如:S = "abababa" 所有的前缀如下:
     
    "a", 长度与出现次数的乘积 1 * 4 = 4,
    "ab",长度与出现次数的乘积 2 * 3 = 6,
    "aba", 长度与出现次数的乘积 3 * 3 = 9,
    "abab", 长度与出现次数的乘积 4 * 2 = 8,
    "ababa", 长度与出现次数的乘积 5 * 2 = 10,
    "ababab", 长度与出现次数的乘积 6 * 1 = 6,
    "abababa", 长度与出现次数的乘积 7 * 1 = 7.
     
    其中"ababa"出现了2次,二者的乘积为10,是所有前缀中最大的。
    Input
    输入字符串S, (1 <= L <= 100000, L为字符串的长度),S中的所有字符均为小写英文字母。
    Output
    输出所有前缀中字符长度与出现次数的乘积的最大值。
    Input示例
    abababa
    Output示例
    10

    题解:

    与上一题类似,只不过此题用next数组回退的方法会超时,因为假如字符串是“aaaaaaaaaa”,那么next每回退一次只会退一个,所以枚举每个位置然后next数组回退的方法,时间复杂度最坏可达O(n^2),所以容易超。故采用递推的方法,时间复杂度为O(n),详情请看代码。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <string>
     6 #include <vector>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <sstream>
    11 #include <algorithm>
    12 using namespace std;
    13 typedef long long LL;
    14 const double eps = 1e-6;
    15 const int INF = 2e9;
    16 const LL LNF = 9e18;
    17 const int MOD = 1e9+7;
    18 const int MAXN = 2e5+10;
    19 
    20 char x[MAXN];
    21 int Next[MAXN];
    22 
    23 void get_next(char x[], int m)
    24 {
    25     int i, j;
    26     j = Next[0] = -1;
    27     i = 0;
    28     while(i<m)
    29     {
    30         while(j!=-1 && x[i]!=x[j]) j = Next[j];
    31         Next[++i] = ++j;
    32     }
    33 }
    34 
    35 int sum[MAXN];
    36 int main()
    37 {
    38     while(scanf("%s", x)!=EOF)
    39     {
    40         int n = strlen(x);
    41         get_next(x, n);
    42 
    43         memset(sum, 0, sizeof(sum));
    44         for(int i = n; i>=1; i--)
    45         {
    46             sum[i]++;
    47             sum[Next[i]] += sum[i];
    48         }
    49         LL ans = 0;
    50         for(int i = 1; i<=n; i++)
    51             ans = max(ans, 1LL*i*sum[i]);
    52         printf("%lld
    ", ans);
    53     }
    54 }
    View Code
  • 相关阅读:
    [ZJOI2010]数字计数
    [SCOI2009]windy数
    [Tjoi2018]数学计算
    [ZJOI2008] 骑士
    [CQOI2009] 中位数
    11.7 模拟赛
    10.31 模拟赛
    随机游走
    10.29 模拟赛
    10.28 模拟赛
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7860677.html
Copyright © 2011-2022 走看看