ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ac自动机

2021-05-05 15:33:08  阅读:169  来源: 互联网

标签:ac int memset tr char vis sizeof 自动机


ac自动机

解决的问题 :

在一个文本串中查找多个模式串.

模板

https://www.luogu.com.cn/problem/P3808

int n,ans;
char s[N];

bool vis[N];
int tr[N][26];
int endd[N];

struct Trie {
	int sz;
	Trie() {
		sz=1;
		memset(tr[0],0,sizeof(tr[0]));
		memset(vis,0,sizeof(vis));
	}

	void insert(char *s) {
		int u =0,n=strlen(s);
		for(int i=0; i<n; i++) {
			int c = s[i] - 'a';
			if(!tr[u][c]) {
				memset(tr[sz],0,sizeof(tr[sz]));
				endd[sz] = 0;
				tr[u][c]=sz++;
			}
			u = tr[u][c];

		}
		endd[u]++;
	}
};

int last[N],f[N];

void print(int j) {
	if(j && !vis[j]) {
		ans += endd[j];
		vis[j] = 1;
		print(last[j]);
	}
}
void build() {
	queue<int>q;
	f[0] = 0;
	for(int i=0; i<26; i++) {
		int u = tr[0][i];
		if(u) {
			f[u] =0,last[u]=0,q.push(u);
		}
	}
	while(!q.empty()) {
		int r=q.front();
		q.pop();
		for(int c=0; c<26; c++) {
			int u = tr[r][c];
			if(!u) {
				tr[r][c] = tr[f[r]][c];
				continue;
			}
			q.push(u);
			int v =f[r];
			while(v && !tr[v][c])v = f[v];
			f[u] = tr[v][c];
			last[u] = endd[f[u]]?f[u]:last[f[u]];
		}
	}
}

void find(char *s){
	int n = strlen(s);
	int j =0;
	for(int i=0;i<n;i++){
		int c = s[i] - 'a';
		j = tr[j][c];
		if(endd[j])print(j);
		else if(last[j])print(last[j]); 
	}
}

void work() {
	scanf("%d",&n);
	Trie trie;
	ans = 0;
	for(int i=1;i<=n;i++){
		scanf("%s",s);
		trie.insert(s);
	}
	build();
	scanf("%s",s);
	find(s);
	printf("%d\n",ans); 
}

查找文章中最多的模块串

https://www.luogu.com.cn/problem/P3796

int n,ans;
char s[N][155];

bool vis[N];
int tr[N][26];
int endd[N];
int id[N];

int num[N];

struct Trie {
	int sz;
	Trie() {
		sz=1;
		memset(tr[0],0,sizeof(tr[0]));
		memset(vis,0,sizeof(vis));
	}

	void insert(char *s,int fa) {
		int u =0,n=strlen(s);
		for(int i=0; i<n; i++) {
			int c = s[i] - 'a';
			if(!tr[u][c]) {
				memset(tr[sz],0,sizeof(tr[sz]));
				endd[sz] = 0;
				tr[u][c]=sz++;
			}
			u = tr[u][c];

		}
		endd[u]++;
		id[u] = fa;  //u这个结点对应fa字符串
	}
};

int last[N],f[N];

void print(int j) {
	if(j && !vis[j]) {
		ans += endd[j];
		num[id[j]]++;  //记录个数
//		vis[j] = 1;
		print(last[j]);
	}
}
void build() {
	queue<int>q;
	f[0] = 0;
	for(int i=0; i<26; i++) {
		int u = tr[0][i];
		if(u) {
			f[u] =0,last[u]=0,q.push(u);
		}
	}
	while(!q.empty()) {
		int r=q.front();
		q.pop();
		for(int c=0; c<26; c++) {
			int u = tr[r][c];
			if(!u) {
				tr[r][c] = tr[f[r]][c];
				continue;
			}
			q.push(u);
			int v =f[r];
			while(v && !tr[v][c])v = f[v];
			f[u] = tr[v][c];
			last[u] = endd[f[u]]?f[u]:last[f[u]];
		}
	}
}

void find(char *s) {
	int n = strlen(s);
	int j =0;
	for(int i=0; i<n; i++) {
		int c = s[i] - 'a';
		j = tr[j][c];
		if(endd[j])print(j);
		else if(last[j])print(last[j]);
	}
}

void work() {
	while(~scanf("%d",&n) && n) {
		Trie trie;
		for(int i=0; i<n; i++) {
			scanf("%s",s[i]);
			trie.insert(s[i],i);
			num[i] = 0;
		}
		build();
		scanf("%s",s[n]);
		find(s[n]);

		int maxn = 0;
		for(int i=0; i<n; i++) {
			if(num[i] > maxn){
				maxn = num[i];
			} 
		}
		printf("%d\n",maxn);
		for(int i=0;i<n;i++){
			if(num[i] == maxn){
				printf("%s\n",s[i]);
			}
		}
	}
}

标签:ac,int,memset,tr,char,vis,sizeof,自动机
来源: https://www.cnblogs.com/LaiYiC/p/14731828.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有