• AC自动机



    本文共三道题目,都是 $ AC $ 自动机的模板题


    初学AC自动机,AC自动机可以理解为“Trie树上KMP”(所以要先学会Trie树和KMP哦!)


    1.Luogu P3808 【模板】AC自动机(简单版)

    Code

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define LL long long
    using namespace std;
    const int N=1000005;
    int n,rot,nxt[N],num[N],trie[N][26];
    char pat[N],txt[N];
    void insert(char s[])
    {
    	int u=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		if(!trie[u][v]) trie[u][v]=++rot;
    		u=trie[u][v];
    	}
    	num[u]++;
    	return;
    }
    void bfs()
    {
    	queue<int> q;
    	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=0;i<26;i++)
    		{
    			if(trie[u][i])
    			{
    				nxt[trie[u][i]]=trie[nxt[u]][i];
    				q.push(trie[u][i]);
    			}
    			else trie[u][i]=trie[nxt[u]][i];
    		}
    	}
    	return;
    }
    int find(char s[])
    {
    	int u=0,res=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		for(int j=trie[u][v];j&&num[j]!=-1;j=nxt[j])
    		{
    			res+=num[j];
    			num[j]=-1;
    		}
    		u=trie[u][v];
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		cin>>(pat+1);
    		insert(pat);
    	}
    	bfs();
    	cin>>(txt+1);
    	printf("%d
    ",find(txt));
    	return 0;
    }
    


    2.Luogu P3796 【模板】AC自动机(加强版)

    Code

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define LL long long
    using namespace std;
    const int N=15005;
    int n,rot,ans,num[N],pos[N],trie[N][26],nxt[N];
    char pat[155][N],txt[1000005];
    void insert(char s[],int b)
    {
    	int u=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		if(!trie[u][v]) trie[u][v]=++rot;
    		u=trie[u][v];
    	}
    	pos[u]=b;
    	return;
    }
    void bfs()
    {
    	queue<int> q;
    	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=0;i<26;i++)
    		{
    			if(trie[u][i])
    			{
    				nxt[trie[u][i]]=trie[nxt[u]][i];
    				q.push(trie[u][i]);
    			}
    			else trie[u][i]=trie[nxt[u]][i];
    		}
    	}
    	return;
    }
    void find(char s[])
    {
    	int u=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		for(int j=trie[u][v];j;j=nxt[j])
    		{
    			if(pos[j])
    			{
    				num[pos[j]]++;
    				ans=max(ans,num[pos[j]]);
    			}
    		}
    		u=trie[u][v];
    	}
    	return;
    }
    int main()
    {
    	while(1)
    	{
    		scanf("%d",&n);
    		if(n==0) break;
    		rot=0;
    		memset(trie,0,sizeof(trie));
    		memset(pos,0,sizeof(pos));
    	    for(int i=1;i<=n;i++)
    	    {
    		    cin>>(pat[i]+1);
    		    insert(pat[i],i);
    	    }
    	    memset(nxt,0,sizeof(nxt));
    	    bfs();
    	    cin>>(txt+1);
    	    ans=0;
    	    memset(num,0,sizeof(num));
    	    find(txt);
    	    printf("%d
    ",ans);
    	    for(int i=1;i<=n;i++) if(num[i]==ans) cout<<(pat[i]+1)<<endl;
    	}
    	return 0;
    }
    


    3.Libre 10057 Keywords Search

    Code

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define LL long long
    using namespace std;
    const int N=5e5+5;
    int T,n,rot,nxt[N],num[N],trie[N][26];
    char pat[55],txt[1000005];
    void insert(char s[])
    {
    	int u=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		if(!trie[u][v]) trie[u][v]=++rot;
    		u=trie[u][v];
    	}
    	num[u]++;
    	return;
    }
    void bfs()
    {
    	queue<int> q;
    	for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=0;i<26;i++)
    		{
    			if(trie[u][i])
    			{
    				nxt[trie[u][i]]=trie[nxt[u]][i];
    				q.push(trie[u][i]);
    			}
    			else trie[u][i]=trie[nxt[u]][i];
    		}
    	}
    	return;
    }
    int find(char s[])
    {
    	int u=0,res=0,len=strlen(s+1);
    	for(int i=1;i<=len;i++)
    	{
    		int v=s[i]-'a';
    		for(int j=trie[u][v];j&&num[j]!=-1;j=nxt[j])
    		{
    			res+=num[j];
    			num[j]=-1;
    		}
    		u=trie[u][v];
    	}
    	return res;
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		rot=0;
    		memset(trie,0,sizeof(trie));
    		memset(num,0,sizeof(num));
    		for(int i=1;i<=n;i++)
    		{
    			cin>>(pat+1);
    			insert(pat);
    		}
    		memset(nxt,0,sizeof(nxt));
    		bfs();
    		cin>>(txt+1);
    		printf("%d
    ",find(txt));
    	}
    	return 0;
    }
    
    Classical is something not fade,but grow more precious with time pass by,so is dream.梦想这东西和经典一样,永远不会因为时间而褪色,反而更显珍贵。
  • 相关阅读:
    dnsever 邮件记录
    用于显示上个月和下个月_PHP
    JSON学习
    ASP生成新会员编号
    godaddy_关于产品退款
    Switch Case语句中多个值匹配同一个代码块的写法
    网闸与防火墙的比较
    bench.sh 跑分测速
    Kcptun加速SS
    linux 安全狗
  • 原文地址:https://www.cnblogs.com/Hawking-llfz/p/11479625.html
Copyright © 2020-2023  润新知