bzoj3620 似乎在梦中见过的样子

好久没有写过KMP了,今天写个KMP练练手。
此题就是枚举左端点暴力,用KMP做到O(n^2)

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std ; 
 4 
 5 const int MAXL = 15000 + 20 ;
 6 
 7 char BUF_OF_T [ MAXL ] ;
 8 int BUF_OF_F [ MAXL ] ;
 9 
10 class KMP {
11     private :
12         char * T ; 
13         int * F ; 
14     public : 
15         KMP ( char * S ) {
16             const int L = strlen ( S ) ; 
17             T = BUF_OF_T ; F = BUF_OF_F ;
18             strcpy ( T , S ) ; F [ 0 ] = -1 ; 
19             for ( int i = 1 ; i <= L ; ++ i ) {
20                 int p = F [ i - 1 ] ; 
21                 while ( p >= 0 && T [ i ] != T [ p + 1 ] ) p = F [ p ] ;
22                 F [ i ] = T [ i ] == T [ p + 1 ] ? p + 1 : -1 ; 
23             }
24         }
25         int * GET_FAIL () const { return F ; } 
26 } ; 
27 
28 char S [ MAXL ] ; 
29 int K ; 
30 int cnt ; 
31 int main () {
32     scanf ( "%s%d" , S , & K ) ;
33     for ( int i = 0 ; S [ i ] != '\0' ; ++ i ) {
34         char * a = S + i ;
35         KMP D ( a ) ; 
36         int * next = D . GET_FAIL () ; 
37         const int L = strlen ( a ) ; 
38         for ( int j = 1 ; j <= L ; ++ j ) { //重点:是1 <= j <= L 不是 1 <= j < L 
39             int & p = next [ j ] ; 
40             while ( p != -1 && next [ p ] + 1 >= K ) p = next [ p ] ;
41             if ( p + 1 >= K && j + 1 - ( p + 1 ) * 2 > 0 ) cnt ++ ;
42         }
43     }
44     printf (  "%d\n" , cnt ) ; 
45     return 0 ;
46 }

 

你可能感兴趣的:(bzoj3620 似乎在梦中见过的样子)