Count the string HDU - 3336 (KMP)

题目链接:https://cn.vjudge.net/contest/303544#problem/D

题目大意:给你一个字符串,问你每个前缀在总的字符串出现的次数之和。

具体思路:在求nex数组的时候,一共有两个版本,nex[0]=-1 和nex[0] =0 的版本。第一个nex[i]代表当前位置匹配失败的时候可以直接跳到哪那里去,第二个nex[i]代表当前位置匹配的后缀最长的时候能到前缀的哪个位置。

a b a b

版本一: -1 0 0 1 2

版本二: 0 0  1 2 0   

然后对于这个题,我们枚举nex数组,每一次往前跳,能跳的步数等于当前位置的最长后缀和前缀的匹配长度。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 const int maxn = 2e5+100;
 5 int nex[maxn];
 6 void get_nex(char str2[])
 7 {
 8     int len=strlen(str2);
 9     int i=0;
10     nex[0]=0;
11     for(int i=1; i<len; i++)
12     {
13         int j=nex[i-1];
14         while(j&&str2[i]!=str2[j])
15             j=nex[j-1];
16         if(str2[i]==str2[j])
17             nex[i]=j+1;
18         else
19             nex[i]=0;
20     }
21 }
22 int kmp(char str1[],char str2[])
23 {
24     get_nex(str2);
25     int len1=strlen(str1);
26     int len2=strlen(str2);
27     int i=0,j=0,ans=0;
28     while(i<len1&&j<len2)
29     {
30         if(str1[i]==str2[j])
31         {
32             i++,j++;
33         }
34         else
35         {
36             if(!j)
37                 i++;
38             else
39                 j=nex[j-1];
40         }
41         if(j==len2)
42         {
43             j=nex[j-1];
44             ans++;
45         }
46     }
47     return ans;
48 }
49 char str1[maxn],str2[maxn];
50 int main()
51 {
52     int T;
53     scanf("%d",&T);
54     while(T--)
55     {
56         int len;
57         scanf("%d",&len);
58         scanf("%s",str1);
59         get_nex(str1);
60         int ans=len;
61         for(int i=0; i<len; i++)
62         {
63             int tmp=i;
64             while(nex[tmp])
65             {
66                 ans++;
67                 tmp=nex[tmp-1];
68             }
69             ans%=10007;
70         }
71         printf("%d\n",ans);
72     }
73         return 0;
74     }

 

posted @ 2019-05-25 10:57  Let_Life_Stop  阅读(184)  评论(0编辑  收藏  举报