欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AC自动机学习总结

程序员文章站 2024-01-29 13:52:10
...

久闻AC自动机的大名,终于,在准备好KMP和字典树之后,开始学习这个看起来高大上的算法了。

多余的写题的时候在补充吧,学完之后发现他的板子并不难,理解也不算太难,网上有很多种写法,近期研究一下,一些代码的常数的问题。洛谷有道题,直接就是板子:

参考不知名大佬的板子(看了好多人的板子了),然后放弃指针,因为觉得要申请空间,好慢啊。

P3808:https://www.luogu.org/problemnew/show/P3808

AC:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
//#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
//#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=5e6+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int mod=998244353;
const double PI=acos(-1.0);
struct node{
	int cnt,fail;
	int nxt[26];
}trie[MAXN];
int que[MAXN];
char s[MAXN];
int ecnt=0;
void Insert(char *s){//获得字典树 
	int id=0,len=strlen(s);
	for(int i=0;i<len;++i){
		int Index=s[i]-'a';
		if(trie[id].nxt[Index]==0)
			trie[id].nxt[Index]=++ecnt;
		id=trie[id].nxt[Index];
	}
	trie[id].cnt++;
}
void get_fail(){//获得fail回溯 
	queue<int> que;
	while(que.size())	que.pop();
	for(int i=0;i<26;++i){
		int Index=trie[0].nxt[i];
		if(Index){
			que.push(Index);
			trie[Index].fail=0;
		}
	}
	while(que.size()){
		int tmp=que.front();que.pop();
		for(int i=0;i<26;++i){
			int Index=trie[tmp].nxt[i];
			if(Index==0){//这里如果没有后面的字符的话,将它与其他的有效字符连起来 
				trie[tmp].nxt[i]=trie[trie[tmp].fail].nxt[i];
				continue;
			}//下面就可以直接连接fail了。 
			trie[Index].fail=trie[trie[tmp].fail].nxt[i];
			que.push(Index);
		}
	}
}
//void get_fail(){
//	int head=0,tail=1;
//	for(int i=0;i<26;++i){
//		int Index=trie[0].nxt[i];
//		if(Index){
//			que[tail++]=Index;
//			trie[Index].fail=0;
//		}
//	}
//	while(head<tail){
//		int tmp=que[head++];
//		for(int i=0;i<26;++i){
//			int Index=trie[tmp].nxt[i];
//			if(Index==0){//失配 
//				trie[tmp].nxt[i]=trie[trie[tmp].fail].nxt[i];
//				continue;
//			}
//			trie[Index].fail=trie[trie[tmp].fail].nxt[i];
//			que[tail++]=Index;
//		}
//	}
//}
int AC_automation(char *s){//判定 
	int id=0,ans=0,len=strlen(s);
	for(int i=0;i<len;++i){
		int Index=trie[id].nxt[s[i]-'a'];
		while(Index&&trie[Index].cnt!=-1){
			ans+=trie[Index].cnt;
			trie[Index].cnt=-1;
			Index=trie[Index].fail;
		}
		id=trie[id].nxt[s[i]-'a'];
	}
	return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%s",s);
        Insert(s);
    }
    get_fail();
    scanf("%s",s);
    printf("%d\n",AC_automation(s));
}


/*
4 2
abcd
bce
abd
cd

abcdefg
*/