zoukankan      html  css  js  c++  java
  • hdu3336 Counting the string kmp的next数组的应用

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3336/

    题意就是要求一个字符串的所有前缀在字符串中出现的次数之和,我们容易想到kmp中的next数组,next[i]=j,表示存在一个长度为j的前缀与长度为j的后缀相同,本题的结果就是要对每一位的next数组都向前回退,回退的次数就是长度不同的前缀出现的次数。还可以采用dp的策略。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned int ui;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 #define pf printf
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 #define prime1 1e9+7
     9 #define prime2 1e9+9
    10 #define pi 3.14159265
    11 #define lson l,mid,rt<<1
    12 #define rson mid+1,r,rt<<1|1
    13 #define scand(x) scanf("%llf",&x) 
    14 #define f(i,a,b) for(int i=a;i<=b;i++)
    15 #define scan(a) scanf("%d",&a)
    16 #define dbg(args) cout<<#args<<":"<<args<<endl;
    17 #define inf 0x3f3f3f3f
    18 #define maxn 1000010
    19 int n,m,t;
    20 int nxt[maxn];
    21 char s[maxn];
    22 void getnxt()
    23 {
    24     int i=-1,j=0;
    25     nxt[0]=-1;
    26     while(j<n)
    27     {
    28         if(i==-1||s[i]==s[j])
    29         {
    30             i++,j++;
    31             nxt[j]=i;//不能用kmp优化的nxt,那样会损失数量 
    32         }
    33         else i=nxt[i];
    34     }
    35 }
    36 int main()
    37 {
    38     //freopen("input.txt","r",stdin);
    39     //freopen("output.txt","w",stdout);
    40     std::ios::sync_with_stdio(false);
    41     scan(t);
    42     while(t--)
    43     {
    44         scan(n);
    45         scanf("%s",s);
    46         getnxt();
    47         int ans=0;
    48         f(i,1,n)//查看以i-1为截至位置的公共前缀后缀 
    49         {
    50             int j=i;
    51             while(j>0)
    52             {
    53                 ans++;//初始时本身还要算一次 
    54                 if(ans>10007)ans-=10007;
    55                 j=nxt[j];
    56             }
    57         }
    58         pf("%d
    ",ans);
    59     }    
    60  } 

    dp:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <time.h>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <algorithm>
     8 using namespace std;
     9 int const MOD = 10007;
    10 int const MAXN = 200010;
    11 char s[MAXN];
    12 int next[MAXN],dp[MAXN];
    13 inline void Get_Next(int n){
    14     memset(next,0,sizeof(next));
    15     for(int i = 1;i < n;i++){
    16         int j = next[i];
    17         while(j && s[i] != s[j]) j = next[j];
    18         if(s[i] == s[j]) next[i + 1] = j + 1;
    19         else next[i + 1] = 0;
    20     }
    21 }
    22 int main(){
    23     int T;
    24     while(~scanf("%d",&T)){
    25         while(T--){
    26             int n;
    27             scanf("%d",&n);
    28             scanf("%s",s);
    29             Get_Next(n);
    30             for(int i = 0;i < n;i++){
    31                 dp[i] = 1;
    32             }
    33             dp[0] = 0;
    34             int sum = 0;
    35             for(int i = 1;i <= n;i++){
    36                 dp[i] = dp[next[i]] + 1;
    37                 sum = (sum + dp[i]) % MOD;
    38             }
    39             printf("%d
    ",sum);
    40         }
    41     }
    42     return 0;
    43 }
  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12517168.html
Copyright © 2011-2022 走看看