【kmp】似乎在梦中见过的样子 BZOJ 3620: 似乎在梦中见过的样子

参考博客:

BZOJ 3620: 似乎在梦中见过的样子

【代码】:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 const int N = 1e5+10;
 7 
 8 char s[N];
 9 int k,n,ans;
10 int Next[N];
11 int main()
12 {
13     scanf("%s%d",s+1,&k);
14     n = strlen( s+1 );
15 
16     //printf("%s %d %d\n",s+1,k,n);
17     //枚举所有合法的左端点,左端点 预留2*k的距离
18     for(int L=1; L<= n-(k*2) ; L++ ) {
19 
20         for(int i = 1 ; i <= L ; i++ ) Next[i] = L-1 ;
21 
22         //提前预处理好Next数组
23         for(int i=L+1,j=L-1;i<=n;i++){
24             while( j != L-1 && s[i] != s[j+1] ) j=Next[j];
25             if( s[i] == s[j+1] ) j++ ;
26             Next[i] = j ;
27         }
28 
29         for(int i=L+1,j=L-1;i<=n;i++){
30             while( j != L-1 && s[i] != s[j+1] ) j=Next[j];
31             if( s[i] == s[j+1] ) j++ ;
32 
33             //预处理的Next派上用场了
34             //当最长前缀的两倍 > 当前串(右端点-左端点)的长度
35             //利用Next数组缩短距离
36             while( (j-L+1)*2 >= (i-L+1) ) j = Next[j] ;
37 
38             //符合题意 累加答案,即前缀长度大于k
39             if( j-L+1 >= k ) ans ++ ;
40         }
41 
42     }
43     printf("%d\n",ans);
44     return 0;
45 }
View Code

猜你喜欢

转载自www.cnblogs.com/Osea/p/11333262.html