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 }