• 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 }
  • 相关阅读:
    FRR and VFR
    MEC in 5G networks
    KNI
    SGX KMRA
    5G E2E issues
    物理层无线信道的特征
    PTP 时钟
    Ransim go through
    网页title闪动JavaScript实现消息提醒
    敏感词库
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12517168.html
Copyright © 2020-2023  润新知