时间复杂度
O(NN−−√)
空间复杂度
O(26∗N)
PS:这份代码跑了1800ms,之后我和csy把代码卡到了421ms,具体代码就不贴了,常数优化而已,其实还能优化一些,懒得改了
my code:
#include <bits/stdc++.h>
using namespace std ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 100005 ;
const int MAXQ = 100005 ;
const int SQR1 = 128 ;
const int SQR2 = 256 ;
vector < int > G[MAXN] ;
char s[MAXN] , ss[MAXN] ;
string p[MAXQ] ;
int op[MAXQ] ;
int nxt[MAXN][26] , fail[MAXN] , idx[MAXN] , in[MAXN] , ou[MAXN] , point , root , dfs_clock ;
int c[1000] , val[MAXN] ;
int n , m ;
int Q[MAXN] , l , r ;
int newnode () {
clr ( nxt[point] , 0 ) ;
return point ++ ;
}
void init () {
point = 0 ;
root = newnode () ;
}
void insert ( string& s , int n , int id ) {
int u = root ;
for ( int i = 0 ; i < n ; ++ i ) {
int x = s[i] - 'a' ;
if ( !nxt[u][x] ) nxt[u][x] = newnode () ;
u = nxt[u][x] ;
}
idx[id] = u ;
}
void dfs ( int u ) {
in[u] = ++ dfs_clock ;
for ( int i = 0 ; i < G[u].size () ; ++ i ) dfs ( G[u][i] ) ;
ou[u] = dfs_clock ;
}
void build () {
l = r = 0 ;
fail[root] = root ;
for ( int i = 0 ; i < 26 ; ++ i ) {
if ( !nxt[root][i] ) nxt[root][i] = root ;
else {
fail[Q[r ++] = nxt[root][i]] = root ;
G[root].push_back ( nxt[root][i] ) ;
}
}
while ( l != r ) {
int u = Q[l ++] ;
for ( int i = 0 ; i < 26 ; ++ i ) {
if ( !nxt[u][i] ) nxt[u][i] = nxt[fail[u]][i] ;
else {
fail[Q[r ++] = nxt[u][i]] = nxt[fail[u]][i] ;
G[nxt[fail[u]][i]].push_back ( nxt[u][i] ) ;
}
}
}
dfs_clock = 0 ;
dfs ( root ) ;
}
inline void add ( int x , int v ) {
c[x / SQR2] += v ;
val[x] += v ;
}
int sum ( int x , int y ) {
int L = x / SQR2 + 1 ;
int R = y / SQR2 - 1 ;
int ans = 0 ;
if ( R + 1 <= L ) {
for ( int i = x ; i <= y ; ++ i ) {
ans += val[i] ;
}
} else {
for ( int i = L ; i <= R ; ++ i ) {
ans += c[i] ;
}
L *= SQR2 ;
R *= SQR2 ;
for ( int i = x ; i < L ; ++ i ) {
ans += val[i] ;
}
for ( int i = R + SQR2 ; i <= y ; ++ i ) {
ans += val[i] ;
}
}
return ans ;
}
int getpos ( char s[] , int L , int R ) {
int u = root ;
for ( int i = L ; i < R ; ++ i ) {
int x = s[i] - 'a' ;
u = nxt[u][x] ;
}
return u ;
}
void addv ( char s[] , int L , int R , int v , int now ) {
int u = now ;
for ( int i = L ; i < R ; ++ i ) {
int x = s[i] - 'a' ;
u = nxt[u][x] ;
add ( in[u] , v ) ;
}
}
void get_fail ( char p[] , int m ) {
fail[1] = 0 ;
for ( int i = 2 , j = 0 ; i <= m ; ++ i ) {
while ( j && p[i] != p[j + 1] ) j = fail[j] ;
if ( p[i] == p[j + 1] ) ++ j ;
fail[i] = j ;
}
}
int kmp ( char s[] , int n , char p[] , int m ) {
int ans = 0 ;
for ( int i = 0 , j = 0 ; i < n ; ++ i ) {
while ( j && s[i] != p[j + 1] ) j = fail[j] ;
if ( s[i] == p[j + 1] ) {
++ j ;
if ( j == m ) {
++ ans ;
j = fail[j] ;
}
} else j = fail[j] ;
}
return ans ;
}
void solve () {
init () ;
for ( int i = 0 ; i < m ; ++ i ) {
scanf ( "%d" , &op[i] ) ;
cin >> p[i] ;
if ( op[i] == 0 && p[i].length () <= SQR1 ) insert ( p[i] , p[i].length () , i ) ;
}
for ( int i = 0 ; i < point ; ++ i ) {
G[i].clear () ;
}
build () ;
clr ( c , 0 ) ;
clr ( val , 0 ) ;
addv ( s , 0 , n , 1 , root ) ;
for ( int i = 0 ; i < m ; ++ i ) {
if ( op[i] ) {
-- op[i] ;
int L = max ( 0 , op[i] - SQR1 ) , R = min ( n , op[i] + SQR1 ) ;
int now = getpos ( s , L , op[i] ) ;
addv ( s , op[i] , R , -1 , now ) ;
s[op[i]] = p[i][0] ;
addv ( s , op[i] , R , 1 , now ) ;
} else {
if ( p[i].length () > SQR1 ) {
int len = 0 ;
for ( int j = 0 ; j < p[i].length () ; ++ j ) {
ss[++ len] = p[i][j] ;
}
get_fail ( ss , len ) ;
printf ( "%d\n" , kmp ( s , n , ss , len ) ) ;
} else {
int ans = sum ( in[idx[i]] , ou[idx[i]] ) ;
printf ( "%d\n" , ans ) ;
}
}
}
}
int main () {
while ( ~scanf ( "%d%d%s" , &n , &m , s ) ) solve () ;
return 0 ;
}