zoukankan      html  css  js  c++  java
  • AC自动机 & 洛谷 P3808 【模板】AC自动机(简单版)& P3796 【模板】AC自动机(加强版)

    传送门(简单版)

    传送门(加强版)


    AC自动机

    推荐阅读:洛谷日报

    讲的真的很好。

    我没法再说的更好了。

    甚至我的板子都是照着他的敲的。

    加强版

    说是加强版,实际上只需更改一下num数组表示的含义:从当前点有几个模式串结尾,改成以当前点结尾的模式串的编号。

    在查询过程中也不需要清空num标记。

    注意数组清空。

    AC代码(简单版)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=1e6+5;
    int tr[maxn][30],cnt,num[maxn],fail[maxn];
    int n;
    string s; 
    void insert(string s){
    	int now=0,len=s.length();
    	for(int i=0;i<len;i++){
    		int k=s[i]-'a';
    		if(!tr[now][k]) tr[now][k]=++cnt;
    		now=tr[now][k];
    	}
    	num[now]++;
    }
    void build(){
    	queue<int> q;
    	for(int i=0;i<26;i++) if(tr[0][i]) q.push(tr[0][i]);
    	while(!q.empty()){
    		int now=q.front();q.pop();
    		for(int i=0;i<26;i++){
    			if(tr[now][i]){
    				fail[tr[now][i]]=tr[fail[now]][i];
    				q.push(tr[now][i]);
    			}else{
    				tr[now][i]=tr[fail[now]][i];
    			}
    		}
    	} 
    } 
    int query(string s){
    	int now=0,res=0,len=s.length();
    	for(int i=0;i<len;i++){
    		now=tr[now][s[i]-'a'];
    		for(int j=now;j&&~num[j];j=fail[j]) res+=num[j],num[j]=-1;
    	}
    	return res;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>s,insert(s);
    	cin>>s;
    	build();
    	cout<<query(s)<<endl;
        return 0;
    }
    

    AC代码(加强版)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=2e4+5;
    int tr[maxn][30],cnt,num[maxn],fail[maxn];
    int n,ans_cnt,ans[maxn],anss[maxn];
    string s[205]; 
    void insert(string s,int id){
    	int now=0,len=s.length();
    	for(int i=0;i<len;i++){
    		int k=s[i]-'a';
    		if(!tr[now][k]) tr[now][k]=++cnt;
    		now=tr[now][k];
    	}
    	num[now]=id;
    }
    void build(){
    	queue<int> q;
    	memset(fail,0,sizeof(fail));
    	for(int i=0;i<26;i++) if(tr[0][i]) q.push(tr[0][i]);
    	while(!q.empty()){
    		int now=q.front();q.pop();
    		for(int i=0;i<26;i++){
    			if(tr[now][i]){
    				fail[tr[now][i]]=tr[fail[now]][i];
    				q.push(tr[now][i]);
    			}else{
    				tr[now][i]=tr[fail[now]][i];
    			}
    		}
    	} 
    } 
    int query(string s){
    	memset(ans,0,sizeof(ans));
    	int now=0,res=0,len=s.length();
    	for(int i=0;i<len;i++){
    		now=tr[now][s[i]-'a'];
    		for(int j=now;j;j=fail[j]) ans[num[j]]++;
    	}
    	for(int i=1;i<=n;i++){
    		if(res<ans[i]){
    			res=ans[i];
    			ans_cnt=0;
    		}
    		if(res==ans[i]) anss[++ans_cnt]=i;
    	}
    	return res;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n;
    	while(n){
    		memset(tr,0,sizeof(tr));
    		memset(num,0,sizeof(num));
    		cnt=ans_cnt=0;
    		for(int i=1;i<=n;i++) cin>>s[i],insert(s[i],i);
    		cin>>s[n+1];
    		build();
    		cout<<query(s[n+1])<<endl;
    		for(int i=1;i<=ans_cnt;i++) cout<<s[anss[i]]<<endl;
    		cin>>n;
    	}
        return 0;
    }
    
  • 相关阅读:
    Mysql --09 Innodb核心特性——事务
    Mysql--08 存储引擎
    MySQL--07 explain用法
    100个网路基础知识
    MySQL06-- mysql索引
    MySQL05-- 客户端工具及SQL语句
    Length of Last Word
    c++将文件之间编译关系降到最低
    c++ string.c_str()小结
    word ladder
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15391486.html
Copyright © 2011-2022 走看看