原题链接

如果直接枚举字符串前缀的子串,再将子串赋值到一个新串,就会O(n^2)超时,因此必须考虑优化

正确思路:

       通过观察规律,我们可以发现当出现前缀在字符串出现次数为1的时候,后面包括这个前缀的新串,在字符串的出现次数也为1,经此优化即可

思路2:

      根据ne数组计数,当ne[i]!=0时,ans++,其意义为以i为结尾的后缀与ne[i]结尾的后缀相同,那么以ne[i]为结尾的前缀在以i结尾的字符串种还会出现一次.

坑点:

      请不要忘记取余,每个ans变化的地方都要取余

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring> 
 4 using namespace std;
 5 const int N = 200010;//不剪枝直接暴力枚举,光枚举时间复杂度是O(n^2),必定TLE,所以需要优化 
 6 const int M = 10007;
 7 char a[N],p[N]; 
 8 int ne[N];
 9 int main()
10 {
11     int t;
12     scanf("%d",&t);
13     while(t--)
14     {
15         int len,ans = 0,cnt = 0;
16         scanf("%d%s",&len,a+1);
17         for(int i=1;i<=len;i++){
18             int idx = 1;
19             if(cnt==1){
20                 ans= (ans+1)%M; continue;
21             }else cnt = 0;
22             while(idx<=i)
23             {
24                 p[idx] = a[idx];//赋值 
25                 idx++;//枚举前缀 
26             }
27             for(int k=2,j=0;k<=i;k++){//求next数组 
28                 while(j&&p[k]!=p[j+1]) j = ne[j];
29                 if(p[k]==p[j+1]) j++;
30                 ne[k] = j;
31             }
32             for(int k=1,j=0;k<=len;k++){//匹配主串与模式串 
33                 while(j&&a[k]!=p[j+1]) j = ne[j];
34                 if(a[k]==p[j+1]) j++;
35                 if(j==i){
36                     ans = (ans+1)%M; j = ne[j]; cnt++; 
37                 }
38             }
39         }
40         printf("%d\n",ans);
41     }
42     return 0;
43 }

 

2021.3.7 二刷完全没想到思路...