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\n",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\n",sum);
40         }
41     }
42     return 0;
43 }

 

posted @ 2020-03-18 14:18  WA自动机~  阅读(110)  评论(0编辑  收藏  举报