模板_KMP和AC自动机

KMP

只贴下代码哈,资料网上很多的啦~

例题 POJ3461

#include 
#include 
#include 
using namespace std;
const int maxn=1000010;
char a[maxn],b[maxn];
int next[maxn],la,lb;

void build(){
	next[0]=0;
	for (int i=1,j=0;i

AC自动机

例题 HDU2222


无优化

insert:

先建字典树

pre:(按照BFS序进行)

失配点:i->fail=j表示1-j是1-i的最大后缀

沿着fa的失配点不断向上找,直到存在next[ch],则当前结点的失配点指向next[ch]。若不存在,则失配点指向root。

work:

扫主串,若不存在next[ch],就沿着fa的失配点不断向上找,直到存在next[ch]。每扫到一个结点,沿着失配点一直退到根节点。过程中,若当前结点有标记,则ans+=count。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=1000010;
char a[maxn],b[60];
struct node{
	int count;
	node *fail,*next[26];
	node(){
		count = 0;
		fail = NULL;
		for (int i=0;i<26;i++)
			next[i] = NULL;
	}
}*root;
queue q;

void insert(){
	node *p = root;
	int len = strlen(b),index;
	for (int i=0;inext[index] == NULL)
			p->next[index] = new node();
		p = p->next[index];
	}
	p->count++;
}

void pre(){
	node *p,*temp;
	q.push(root);
	while (!q.empty()){
		p = q.front();
		q.pop();
		for (int i=0;i<26;i++)
			if (p->next[i] != NULL){
				temp = p->fail;
				while (temp != NULL){
					if (temp->next[i] != NULL){
						p->next[i]->fail = temp->next[i];
						break;
					}
					temp = temp->fail;
				}
				if (temp == NULL)	p->next[i]->fail = root;
				q.push(p->next[i]);
			}
	}
}

void work(){
	node *p = root,*temp;
	int ans = 0,len = strlen(a),index;
	for (int i=0;inext[index] == NULL && p != root)
			p = p->fail;
		p = p->next[index];
		if (p == NULL) p = root;
		temp = p;
		while (temp != root && temp->count != -1){
			ans += temp->count;
			temp->count = -1;
			temp = temp->fail;
		}
	}
	printf("%d\n",ans);
}

int main(){
	int t,n;
	scanf("%d",&t);
	for (int i=0;i

加优化

增加失配边(仍用next数组表示),就不需要一直回溯找失配点,只要找当前结点的失配边。

p->next[ch]即为p->fail->next[ch]。(失配边

p->next[i]->fail 即为 p->fail->next[i]。(失配点)

仍按照BFS序进行。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=1000010;
char a[maxn],b[60];
struct node{
	int count;
	node *fail,*next[26];
	node(){
		count = 0;
		fail = NULL;
		for (int i=0;i<26;i++)
			next[i] = NULL;
	}
}*root;
queue q;

void insert(){
	node *p = root;
	int len = strlen(b),index;
	for (int i=0;inext[index] == NULL)
			p->next[index] = new node();
		p = p->next[index];
	}
	p->count++;
}

void pre(){
	node *p(root),*temp;
	for (int i=0;i<26;i++)
		if (p->next[i] != NULL){
			p->next[i]->fail = root;
			q.push(p->next[i]);
		}
		else p->next[i] = root;
	while (!q.empty()){
		p = q.front();
		q.pop();
		for (int i=0;i<26;i++)
			if (p->next[i] != NULL){
				p->next[i]->fail = p->fail->next[i];
				q.push(p->next[i]);
			}
			else p->next[i] = p->fail->next[i];
	}
}

void work(){
	node *p = root,*temp;
	int ans = 0,len = strlen(a),index;
	for (int i=0;inext[index];
		if (p == NULL) p = root;
		temp = p;
		while (temp != root && temp->count != -1){
			ans += temp->count;
			temp->count = -1;
			temp = temp->fail;
		}
	}
	printf("%d\n",ans);
}

int main(){
	int t,n;
	scanf("%d",&t);
	for (int i=0;i


你可能感兴趣的:(字符串,板子)