HDU 2222 AC自动机 裸题

题意:

问母串中出现多少个模式串

注意ac自动机的节点总数

 

 

 

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}
inline int Min(int a,int b){return a>b?b:a;}
int ANS;


#define N 1000010
#define maxnode 250001
#define sigma_size 26

struct Trie{
	int ch[maxnode][sigma_size];
	int val[maxnode];
	int last[maxnode];
	int f[maxnode];
	int sz;
	void init(){
		sz=1;
		memset(ch,0,sizeof(ch));
		memset(val, 0, sizeof(val));
		memset(f,0,sizeof(f));
		memset(last,0,sizeof(last));
	}
	int idx(char c){
		return c-'a';
	}
	void print(int j){
		if(j){
			printf("%d: %d\n", j, val[j]);
			print(last[j]);
		}
	}
	void Creat(char *s){
		int u = 0, len = strlen(s);
		for(int i = 0;i < len;i++){
			int c = idx(s[i]);
			if(!ch[u][c])
				ch[u][c] = sz++;

			u = ch[u][c];
		}
		val[u] ++;
	}
	void getFail(){
		queue<int> q;
		for(int i = 0; i<sigma_size; i++)
			if(ch[0][i]) q.push(ch[0][i]);

		while(!q.empty()){
			int r = q.front(); q.pop();
			for(int c = 0; c<sigma_size; c++){
				int u = ch[r][c];
				if(!u)continue;
				q.push(u);
				int v = f[r];
				while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
				f[u] = ch[v][c];
				last[u] = val[f[u]] ? f[u] : last[f[u]];
			}
		}
	}
	void find(char *T){
		int len = strlen(T), j = 0;
		for(int i = 0; i < len; i++){
			int c = idx(T[i]);
			while(j && ch[j][c]==0) j = f[j];
			j = ch[j][c];

			int temp = j;
			while(temp && val[temp]){
				ANS += val[temp];
				val[temp] = 0;
				temp = f[temp];
			}
		}
	}
};
Trie ac;
char S1[N];
int Slen;

void InputString(){
	scanf("%s",S1);
	Slen = strlen(S1);
	S1[Slen]='\0';
}
int main(){

	int T,i,j,n;scanf("%d",&T);

	while(T--){
		ac.init();
		scanf("%d",&n);
		while(n--){
			scanf("%s",S1);
			ac.Creat(S1);
		}
		ac.getFail();
		InputString();
		ANS = 0;
		ac.find(S1);

		printf("%d\n",ANS);

	}
	return 0;
}
/*
1
5
she
he
say
shr
her
yasherhs

ans:
3



*/


posted on 2013-10-07 20:57  you Richer  阅读(316)  评论(0)    收藏  举报