洛谷专题-AC自动机

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

题意:

本题就是一个最裸的AC自动机模板,问有多少个模式串在文本串中出现,直接套板子即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
 using namespace std;
 const int maxn=500010;
 queue<int> q;
 struct AC_Automachine{
     int c[maxn][26],val[maxn],fail[maxn],cnt;
     void ins(char *s){
         int len=strlen(s);int now=0;
         for(int i=0;i<len;i++){
             int v=s[i]-'a';
             if(!c[now][v]) c[now][v]=++cnt;
             now=c[now][v];
         }
        val[now]++;
     }
     void build(){
         for(int i=0;i<26;i++){
             if(c[0][i]){
                 fail[c[0][i]]=0;
                 q.push(c[0][i]);
             } 
         }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=0;i<26;i++){
                if(c[u][i]){
                    fail[c[u][i]]=c[fail[u]][i];
                    q.push(c[u][i]);
                }
                else c[u][i]=c[fail[u]][i];
            }
        }
     }
     int query(char *s){
         int len=strlen(s);
         int now=0,ans=0;
         for(int i=0;i<len;i++){
             now=c[now][s[i]-'a'];
             for(int t=now;t&&~val[t];t=fail[t])
                 ans+=val[t],val[t]=-1;
         }
         return ans;
     }
 }AC;
 int n;
 char p[1000005];
 int main()
 {
     scanf("%d",&n);
     for(int i=1;i<=n;i++) scanf("%s",p),AC.ins(p);
     AC.build();
     scanf("%s",p);
     int ans=AC.query(p);
     cout<<ans<<endl;
     return 0;
 }
View Code

P3796【模板】AC自动机加强版

题意:

这题是询问哪个模式串出现次数最多,输出出现次数与串,有多个则输出多个,做法也不难,开一个ans[i]数组记录模式串i的出现次数,然后求出最大值,再遍历一遍ans数组,输出与最大值相同的下标对应的字符串。还有一点不同的就是,对于insert操作对每个模式串结尾的标记应该改为模式串的编号才能在ans数组中记录

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
 using namespace std; 
 const int maxn=300000;
 string s[160],temp;
 int ans[maxn],n;
 struct AC_Automachine{
     int c[maxn][26],val[maxn],fail[maxn],cnt;
     void init(){
         memset(c,0,sizeof(c));
         memset(ans,0,sizeof(ans));
         memset(val,0,sizeof(val));
         memset(fail,0,sizeof(fail));
         cnt=0;
     }
     void insert(string s,int k){
         int now=0;
         for(int i=0;i<s.length();i++){
             int v=s[i]-'a';
             if(!c[now][v]) c[now][v]=++cnt;
             now=c[now][v];
         }
        val[now]=k;
     }
    void build(){
        queue<int> q;
        for(int i=0;i<26;i++){
            if(c[0][i]){
                fail[c[0][i]]=0;
                q.push(c[0][i]);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=0;i<26;i++){
                if(c[u][i]){
                    fail[c[u][i]]=c[fail[u]][i];
                    q.push(c[u][i]);
                }
                else c[u][i]=c[fail[u]][i];
            }
        }
    }
    void query(string s){
        int now=0;
        for(int i=0;i<s.length();i++){
            now=c[now][s[i]-'a'];
            for(int t=now;t;t=fail[t])
                ans[val[t]]++;
        }
    }
 }AC;
 int main()
 {
     while(scanf("%d",&n)&&n){
         AC.init();
         for(int i=1;i<=n;i++){
             cin>>s[i];
             AC.insert(s[i],i);
         }
         AC.build();
         cin>>temp;
         AC.query(temp);
         int pos=0;
         for(int i=1;i<=n;i++) pos=max(pos,ans[i]);
         cout<<pos<<endl;
         for(int i=1;i<=n;i++) if(ans[i]==pos) cout<<s[i]<<endl; 
     }
 }
View Code

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12329507.html