人裂开,像我这种纯指针的AC自动机写法有用fail树优化的办法嘛?
查看原帖
人裂开,像我这种纯指针的AC自动机写法有用fail树优化的办法嘛?
119638
xia0ji233楼主2021/4/8 19:26
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
typedef struct A{
	int word;
	A* fail;
	A* next[26];
	void aaa(){
		word=0;
		fail=NULL;
		for(int i=0;i<26;i++)
			next[i]=NULL;
	}
}node;
node *root;
queue<node*>q;
char t[2000010],word[2000010];
int num[200000];
void insert(int x){
	node *p=root;
	int len=strlen(word);
	for(int i=0;i<len;i++){
		int k=word[i]-'a';
		if(p->next[k]==NULL){
			node *new_node=new node;
			new_node->aaa();
			p->next[k]=new_node;
		}
		p=p->next[k];
	}
	if(p->word){
		num[x]=p->word-x;
	}
	else p->word=x;
}
void build_fail(){
	q.push(root);
	while(!q.empty()){
		node *p=q.front();
		q.pop();
		for(int i=0;i<26;i++){
			if(p->next[i]!=NULL){
				node *k=p->next[i];
				q.push(k);
				if(p==root){
					k->fail=root;
				}
				else{
					node *fafail=p->fail;
					while(fafail!=NULL){
						if(fafail->next[i]!=NULL){
							k->fail=fafail->next[i];
							break;
						}
						fafail=fafail->fail;
					}
					if(fafail==NULL)k->fail=root;
				}
			}
		}
	}
}
void query(){
	int len=strlen(t);
	node *p=root;
	for(int i=0;i<len;i++){
		int k=t[i]-'a';
		while(p->next[k]==NULL&&p!=root)p=p->fail;
		p=p->next[k];
		if(p==NULL)p=root;
		else{
			node *temp=p;
			while(temp!=root){
				if(temp->word){
					num[temp->word]++;
				}
				temp=temp->fail;
			}
		}
	}
}
int main(){
	//freopen("in.txt","r",stdin);
	int n;
	scanf("%d",&n);
	root=new node;
	root->aaa();
	for(int i=1;i<=n;i++){
		scanf("%s",word);
		insert(i);
	}
	build_fail();
	scanf("%s",t);
	query();
	for(int i=1;i<=n;i++){
		if(num[i]>=0)cout<<num[i]<<endl;
		else cout<<num[num[i]+i]<<endl;
	}
	return 0;
}
2021/4/8 19:26
加载中...