【codeforces】163E. e-Government AC自动机+树状数组

传送门:【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 ;
}


你可能感兴趣的:(codeforces)