AC自动机(模板)

指针写法:
博客来源:AC自动机算法详解

#include<bits/stdc++.h>
using namespace std;
const int N = 1000 * 100 + 10,M=26;
int head, tail;

struct node{
	node *fail;
	node *nextt[M];
	int cnt;
	node() {
		fail = NULL;
		cnt = 0;
		for (int i = 0; i < 26; i++)nextt[i] = NULL;
	}
}*q[N],*root;

void Insert(char *str, node *root) {
	node *p = root;
	int i = 0,index;
	while (str[i]) {
		index = str[i] - 'a';
		if (p->nextt[index] == NULL) {
			p->nextt[index] = new node();
		}
		p - p->nextt[index];
		i++;
	}
	p->cnt++;
}

void build_fail(node *root) {
	int i;
	root->fail = NULL;
	q[head++] = root;
	while (head != tail) {
		node *temp = q[tail++];
		node *p = NULL;
		for (int i = 0; i < M; i++) {
			if (temp->nextt[i] != NULL) {
				if (temp == root)temp->nextt[i]->fail = root;
				else {
					p = temp->fail;
					while (p) {
						if (p->nextt[i]) {
							temp->nextt[i]->fail = p->nextt[i];
							break;
						}
						p = p->fail;
					}
					if (p == NULL)temp->nextt[i]->fail = root;
				}
				q[head++] = temp->nextt[i];
			}
		}
	}
}

int query(node *root, char *str) {
	int i = 0, cnt = 0, index, len = strlen(str);
	node *p = root;
	while (str[i]) {
		index = str[i] - 'a';
		while (p->nextt[index] == NULL && p != root)p = p->fail;
		p = p->nextt[index];
		p = p == NULL ? root : p;
		node *temp = p;
		while (temp != root && temp->cnt != -1) {
			cnt += temp->cnt;
			temp->cnt = -1;
			temp = temp->fail;
		}
		i++;
	}
	return cnt;
}

int main() {

	char str[10000];
	root = new node();
	while (scanf("%s", str), str[0]= '#') {
		Insert(str,root);
	}
	build_fail(root);
	scanf("%s",str);
	cout << query(root,str);
	return 0;
}

数组写法:
博客来源:AC自动机总结及板子

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define il inline
#define RG register
#define N 10010
using namespace std;

char s[N][55], ss[N * 100];
int n, times[N];//times记录单词在文本串中出现的次数 

struct Trie {
	int son[N][26], fail[N], root, L, num[N];
	int last[N];//只是一个优化,有没有都没关系

	void init() {
		L = 1; root = 0;
		memset(son, 0, sizeof(son));
		memset(num, 0, sizeof(num));
		memset(last, 0, sizeof(last));
		memset(fail, 0, sizeof(fail));
	}

	il int idx(char c) { return c - 'a'; }

	void insert(char s[], int v) {
		int len = strlen(s), cur = root;
		for (int i = 0; i < len; i++) {
			int id = idx(s[i]);
			if (!son[cur][id])
				son[cur][id] = L++;
			cur = son[cur][id];
		}
		num[cur] = v;   //记录单词编号
	}

	void build() {
		int que[N], hd = 0, tl = 0;
		for (int i = 0; i < 26; i++)
			if (son[root][i]) {
				que[tl++] = son[root][i];
				fail[son[root][i]] = root;
			}
			else son[root][i] = root;

		while (hd < tl) {
			int cur = que[hd++];
			for (int i = 0; i < 26; i++) {
				int Son = son[cur][i];
				if (Son) {
					int f = fail[cur];
					while (f && !son[f][i]) f = fail[f];
					fail[Son] = son[f][i];
					//num[Son]=num[fail[Son]];//不要管这一句
					que[tl++] = Son;
				}
				else son[cur][i] = son[fail[cur]][i];
			}
			//if( num[fail[cur]] )last[cur]=fail[cur];
			//else last[cur]=last[fail[cur]];
		}
	}

	void query(char s[]) {
		int len = strlen(s), cur = root;
		for (int i = 0; i < len; i++) {
			int id = idx(s[i]);
			while (cur && !son[cur][id]) cur = fail[cur];
			if (son[cur][id]) {
				cur = son[cur][id];
				int k = cur;
				while (k) times[num[k]]++, k = fail[k];
				/*while(k){
				  if(num[k]) times[num[k]]++;
				  k=last[k];
				  }*/
			}

		}
	}

}AC;

int main() {
	scanf("%d", &n); AC.init();
	for (RG int i = 1; i <= n; i++) {
		scanf("%s", s[i]);
		AC.insert(s[i], i);
	}
	AC.build();
	scanf("%s", ss); AC.query(ss);
	for (RG int i = 1; i <= n; i++)    printf("%s %d\n", s[i], times[i]);
	return 0;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值