hdu 3065 AC自动机模版题

题意:输出每个模式串出现的次数,查询的时候呢使用一个数组进行记录就好。

同上题一样的关键点,其他没什么难度了。

#include <cstdio>

#include <cstring>

#include <queue>



using namespace std;



const int maxw = 1000 * 50 + 10;

const int sigma_size = 128;

const int maxl = 2000000 + 10;



char str[1010][100];



struct Trie{

	int next[maxw][sigma_size],fail[maxw],end[maxw];

	int root,L;

	int newnode(){

		for(int i=0;i<sigma_size;i++)

		    next[L][i]=-1;

		end[L++]=-1;

		return L-1;

	}

	void init(){

		L=0;

		root=newnode();

	}

	void insert(const char *s,int id){

		int now=root,len=strlen(s);

		for(int i=0;i<len;i++){

			if(next[now][s[i]]==-1)

			    next[now][s[i]]=newnode();

			now=next[now][s[i]];

		}

		end[now]=id;

	}

	void build(){

		queue<int>Q;

		fail[root]=root;

		for(int i=0;i<sigma_size;i++)

		    if(next[root][i]==-1)

		        next[root][i]=root;

		    else{

		    	fail[next[root][i]]=root;

		    	Q.push(next[root][i]);

		    }

		while(!Q.empty()){

			int now=Q.front();

			Q.pop();

			for(int i=0;i<sigma_size;i++)

			    if(next[now][i]==-1)

			        next[now][i]=next[fail[now]][i];

			    else{

			    	fail[next[now][i]]=next[fail[now]][i];

			    	Q.push(next[now][i]);

			    }

		}

	}

	int num[1000 + 10];

	void query(const char *buf,int n){

		memset(num,0,sizeof(num));

		int now=root,len=strlen(buf);

		for(int i=0;i<len;i++){

			now=next[now][buf[i]];

			int tmp=now;

			while(tmp!=root){

				if(end[tmp]!=-1)

				    num[end[tmp]]++;

				tmp=fail[tmp];

			}

		}

		for(int i=0;i<n;i++)

		  if(num[i])

		    printf("%s: %d\n",str[i],num[i]);

	}

};



char buf[maxl];

Trie ac;



int main()

{

	int n;

	while(~scanf("%d",&n)){

		ac.init();

		for(int i=1;i<=n;i++){

			scanf("%s",str[i]);

			ac.insert(str[i],i);

		}

		ac.build();

		scanf("%s",buf);

		ac.query(buf,n);

	}

	return 0;

}


 

 

你可能感兴趣的:(AC自动机)