传送门:【codeforces】163E. e-Government
题目分析:感觉到现在再做类似题目已经感觉很水了= =。。。这题也就是构建了fail指针树以后树状数组维护就好了。10^6个字母的意思就是说我们可以随便搞。。。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; typedef long long LL ; #define rep( i , a , b ) for ( int i = a ; i < b ; ++ i ) #define For( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define rev( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 1000005 ; const int MAXE = 1000005 ; struct Edge { int v , n ; Edge () {} Edge ( int var , int next ) : v ( var ) , n ( next ) {} } ; struct ac_automaton { int next[MAXN][26] ; int fail[MAXN] ; int word[MAXN] ; int root ; int cur ; int Q[MAXN] ; int head ; int tail ; int T[MAXN] ; int in[MAXN] ; int ou[MAXN] ; int dfs_clock ; Edge E[MAXE] ; int H[MAXN] , cntE ; bool a[MAXN] ; int newnode () { rep ( i , 0 , 26 ) next[cur][i] = -1 ; return cur ++ ; } void init () { cur = 0 ; cntE = 0 ; dfs_clock = 0 ; clr ( a , 0 ) ; clr ( T , 0 ) ; clr ( H , -1 ) ; root = newnode () ; } void addedge ( int u , int v ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ; } void insert ( char buf[] , int idx ) { int now = root ; for ( int i = 0 ; buf[i] ; ++ i ) { int x = buf[i] - 'a' ; if ( next[now][x] == -1 ) next[now][x] = newnode () ; now = next[now][x] ; } word[idx] = now ; } void build () { head = tail = 0 ; fail[root] = root ; rep ( i , 0 , 26 ) { if ( ~next[root][i] ) { fail[next[root][i]] = root ; Q[tail ++] = next[root][i] ; } else next[root][i] = root ; } while ( head != tail ) { int now = Q[head ++] ; rep ( i , 0 , 26 ) { if ( ~next[now][i] ) { fail[next[now][i]] = next[fail[now]][i] ; Q[tail ++] = next[now][i] ; } else next[now][i] = next[fail[now]][i] ; } } rep ( i , 1 , cur ) addedge ( fail[i] , i ) ; } void dfs ( int u ) { in[u] = ++ dfs_clock ; for ( int i = H[u] ; ~i ; i = E[i].n ) dfs ( E[i].v ) ; ou[u] = dfs_clock ; } int sum ( int x , int ans = 0 ) { for ( int i = x ; i <= dfs_clock ; i += i & -i ) ans += T[i] ; return ans ; } void add ( int x , int v ) { for ( int i = x ; i ; i -= i & -i ) T[i] += v ; } void query ( char buf[] ) { int now = root ; LL ans = 0 ; for ( int i = 0 ; buf[i] ; ++ i ) { now = next[now][buf[i] - 'a'] ; //printf ( "%d %d %d\n" , ou[now] , in[now] , sum ( in[now] ) ) ; ans += sum ( in[now] ) ; } printf ( "%I64d\n" , ans ) ; } void modify ( int x , int sign ) { int now = word[x] ; if ( a[x] == 0 && sign == -1 || a[x] == 1 && sign == 1 ) return ; if ( a[x] == 0 ) { a[x] = 1 ; add ( ou[now] , 1 ) ; add ( in[now] - 1 , -1 ) ; } else { a[x] = 0 ; add ( ou[now] , -1 ) ; add ( in[now] - 1 , 1 ) ; } } } ; ac_automaton ac ; char buf[MAXN] ; int n , k ; void solve () { char op ; int x ; ac.init () ; For ( i , 1 , k ) { scanf ( "%s" , buf ) ; ac.insert ( buf , i ) ; } ac.build () ; ac.dfs ( ac.root ) ; For ( i , 1 , k ) ac.modify ( i , 1 ) ; while ( n -- ) { scanf ( " %c" , &op ) ; if ( op == '?' ) { scanf ( "%s" , buf ) ; ac.query ( buf ) ; } else { scanf ( "%d" , &x ) ; ac.modify ( x , op == '+' ? 1 : -1 ) ; } } } int main () { while ( ~scanf ( "%d%d" , &n , &k ) ) solve () ; return 0 ; }