题目链接: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
",ans);
72 }
73 return 0;
74 }