AC_automaton,AC自动机模板

/*
    AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
    最简单的模板,需要修改
 */
const int N = maxn*8;  //N表示n*m,n为模式串的个数,m为模式串的长度
struct AC_automaton {
    int tr[N][26], tot;
    int e[N], fail[N];
    void init(){
        memset(tr, 0, sizeof(tr));
        memset(e, 0, sizeof(e));
        memset(fail, 0, sizeof(fail));
    }
    void insert(char *s) {
        int u = 0;
        for (int i = 1; s[i]; i++) {
            if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot;
            u = tr[u][s[i] - 'a'];
        }
        e[u]++;        //模式串有可能有一样的
    }
    queue<int> q;
    void build() {    //fail指针的构建
        for (int i = 0; i < 26; i++)
            if (tr[0][i]) q.push(tr[0][i]);
        while (q.size()) {
            int u = q.front();
            q.pop();
            for (int i = 0; i < 26; i++) {
                if (tr[u][i])
                    fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
                else
                    tr[u][i] = tr[fail[u]][i];
            }
        }
    }
    int query(char *t) {
        int u = 0, res = 0;
        for (int i = 1; t[i]; i++) {
            u = tr[u][t[i] - 'a'];  // 转移
            for (int j = u; j && e[j] != -1; j = fail[j]) {        //如果存在以此为结尾的话就增加一个匹配串
                res += e[j], e[j] = -1;
            }
        }
        return res;
    }
}ac;

洛谷模板一,简单版

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
/*
	AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
	最简单的模板,
 */
const int N = maxn*8;  //N表示n*m,n为模式串的个数,m为模式串的长度
struct AC_automaton {
	int tr[N][26], tot;
	int e[N], fail[N];
	void init(){
		memset(tr, 0, sizeof(tr));
		memset(e, 0, sizeof(e));
		memset(fail, 0, sizeof(fail));
	}
	void insert(char *s) {
		int u = 0;
		for (int i = 1; s[i]; i++) {
			if (!tr[u][s[i] - 'a']) tr[u][s[i] - 'a'] = ++tot;
			u = tr[u][s[i] - 'a'];
		}
		e[u]++;		//模式串有可能有一样的
	}
	queue<int> q;
	void build() {	//fail指针的构建
		for (int i = 0; i < 26; i++)
			if (tr[0][i]) q.push(tr[0][i]);
		while (q.size()) {
			int u = q.front();
			q.pop();
			for (int i = 0; i < 26; i++) {
				if (tr[u][i])
					fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
				else
					tr[u][i] = tr[fail[u]][i];
			}
		}
	}
	int query(char *t) {
		int u = 0, res = 0;
		for (int i = 1; t[i]; i++) {
		    u = tr[u][t[i] - 'a'];  // 转移
		    for (int j = u; j && e[j] != -1; j = fail[j]) {		//如果存在以此为结尾的话就增加一个匹配串
		    	res += e[j], e[j] = -1;
		    }
		}
		return res;
	}
}ac;
char str[maxn];
int main(){
	int n;scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%s", str+1), ac.insert(str);
	ac.build();
	scanf("%s", str+1);
	printf("%d\n", ac.query(str));
	return 0;
}

洛谷模板二加强版

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
const int N = 156*80;
/*
	AC自动机,对多个模式串匹配,查找给出的文本串有多少个出现在模式串中
 */
struct AC_automaton {
	int tr[N][26], tot;	//tr为字典树
	int e[N], fail[N],val[N];	//e为模式串结尾异或,fail为失配指针,val记录出现次数
	int cnt[N];			//cnt记录模式串在文本串中出现的次数
	void init() {
	  memset(fail, 0, sizeof(fail));
	  memset(tr, 0, sizeof(tr));
	  memset(val, 0, sizeof(val));
	  memset(cnt, 0, sizeof(cnt));
	  memset(e, 0, sizeof(e));
	  tot = 0;
	}
	void insert(char *s, int id) {
		int u = 0;
		for (int i = 0; s[i]; i++) {
			if (!tr[u][s[i]-'a']) tr[u][s[i]-'a'] = ++tot;
			u = tr[u][s[i]-'a'];
		}
		e[u]=id;
	}
	queue<int> q;
	void build() {
		for (int i = 0; i < 26; i++)
			if (tr[0][i]) q.push(tr[0][i]);
		while (q.size()) {
			int u = q.front();
			q.pop();
			for (int i = 0; i < 26; i++) {
				if (tr[u][i])
					fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
				else
					tr[u][i] = tr[fail[u]][i];
			}
		}
	}
	int query(char *t) {		//返回最大的出现次数
		int u = 0, res = 0;
		for (int i = 0; t[i]; i++) {
		    u = tr[u][t[i] - 'a'];  // 转移
		    for (int j = u; j ; j = fail[j]) {
		    	val[j]++;
		    }
		}
		for(int i = 0; i <= tot; i++){
			if(e[i]){
				res=max(res, val[i]);
				cnt[e[i]]=val[i];
			}
		}
		return res;
	}
}ac;
char s[200][80];
char str[maxn];
int main() {
	int n;
	while(scanf("%d", &n), n){
		ac.init();
		for(int i = 1; i <= n; i++) scanf("%s", s[i]), ac.insert(s[i], i);
		scanf("%s", str);
		ac.build();
		int x=ac.query(str);
		printf("%d\n", x);
		for(int i = 1; i <= n; i++){
			if(ac.cnt[i]==x) printf("%s\n", s[i]);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值