AC自动机专题

AC自动机专题

先开个坑

按照惯例,先来模板

就以hdu2222的代码作为模板吧,就是在字典树上连上一些失配边,这个模板将不存在的子结点直接当成失配边连到根,对所有的转移都一视同仁。失配时候的转移和kmp是一样的道理,只是kmp是在链上转移,而自动机是在树上转移。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>

using namespace std;

const int maxn=500100;

struct Trie
{
    int ch[maxn][26],end[maxn];
    int f[maxn];
    int rt,L;
    int newnode()
    {
        memset(ch[L],-1,sizeof(ch[L]));
        end[L]=0;
        return L++;
    }
    void init()
    {
        L=0;
        rt=newnode();
    }
    void insert(char *s)
    {
        int u=rt;
        int len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(ch[u][c]==-1) ch[u][c]=newnode();
            u=ch[u][c];
        }
        end[u]++;
    }
    void build()
    {
        queue<int> q;
        f[rt]=rt;
        for(int c=0;c<26;c++){
            if(ch[rt][c]==-1) ch[rt][c]=rt;
            else{
                f[ch[rt][c]]=rt;
                q.push(ch[rt][c]);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int c=0;c<26;c++){
                if(ch[u][c]==-1) ch[u][c]=ch[f[u]][c];
                else{
                    f[ch[u][c]]=ch[f[u]][c];
                    q.push(ch[u][c]);
                }
            }
        }
    }
    int find(char *s)
    {
        int len=strlen(s);
        int u=rt;
        int res=0;
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            u=ch[u][c];
            int t=u;
            while(t!=rt){
                res+=end[t];
                end[t]=0;
                t=f[t];
            }
        }
        return res;
    }
};
Trie ac;
char s[maxn*3];
int n;

int main()
{
    int T;cin>>T;
    while(T--){
        ac.init();
        scanf("%d",&n);
        while(n--){
            scanf("%s",s);
            ac.insert(s);
        }
        ac.build();
        scanf("%s",s);
        printf("%d\n",ac.find(s));
    }
    return 0;
}
View Code

 

hdu2222: Keywords Search

第一道AC自动机,最简单的模板题。每走一个字符就按失配边走到根,把沿途经过的字符串个数记录下来并将其设为0(也就是统计。。。。。。)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>

using namespace std;

const int maxn=500100;

struct Trie
{
    int ch[maxn][26],end[maxn];
    int f[maxn];
    int rt,L;
    int newnode()
    {
        memset(ch[L],-1,sizeof(ch[L]));
        end[L]=0;
        return L++;
    }
    void init()
    {
        L=0;
        rt=newnode();
    }
    void insert(char *s)
    {
        int u=rt;
        int len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            if(ch[u][c]==-1) ch[u][c]=newnode();
            u=ch[u][c];
        }
        end[u]++;
    }
    void build()
    {
        queue<int> q;
        f[rt]=rt;
        for(int c=0;c<26;c++){
            if(ch[rt][c]==-1) ch[rt][c]=rt;
            else{
                f[ch[rt][c]]=rt;
                q.push(ch[rt][c]);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int c=0;c<26;c++){
                if(ch[u][c]==-1) ch[u][c]=ch[f[u]][c];
                else{
                    f[ch[u][c]]=ch[f[u]][c];
                    q.push(ch[u][c]);
                }
            }
        }
    }
    int find(char *s)
    {
        int len=strlen(s);
        int u=rt;
        int res=0;
        for(int i=0;i<len;i++){
            int c=s[i]-'a';
            u=ch[u][c];
            int t=u;
            while(t!=rt){
                res+=end[t];
                end[t]=0;
                t=f[t];
            }
        }
        return res;
    }
};
Trie ac;
char s[maxn*3];
int n;

int main()
{
    int T;cin>>T;
    while(T--){
        ac.init();
        scanf("%d",&n);
        while(n--){
            scanf("%s",s);
            ac.insert(s);
        }
        ac.build();
        scanf("%s",s);
        printf("%d\n",ac.find(s));
    }
    return 0;
}
View Code

 

hdu2896:病毒侵袭

很简单,开个vector记录id,直接匹配就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>

using namespace std;

const int maxn=80010;
const int SIZE=128;

int N,M;
char s[maxn];
set<int> ans;
struct Trie
{
    int ch[maxn][SIZE],f[maxn];
    vector<int> id[maxn];
    int rt,L;
    int newnode()
    {
        memset(ch[L],-1,sizeof(ch[L]));
        id[L].clear();
        return L++;
    }
    void init()
    {
        for(int i=0;i<maxn;i++) id[i].clear();
        L=0;
        rt=newnode();
    }
    void insert(char *s,int ID)
    {
        int u=rt;
        int len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i];
            if(ch[u][c]==-1) ch[u][c]=newnode();
            u=ch[u][c];
        }
        id[u].push_back(ID);
    }
    void build()
    {
        queue<int> q;
        f[rt]=rt;
        for(int c=0;c<SIZE;c++){
            if(ch[rt][c]==-1) ch[rt][c]=rt;
            else{
                f[ch[rt][c]]=rt;
                q.push(ch[rt][c]);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int c=0;c<SIZE;c++){
                if(ch[u][c]==-1) ch[u][c]=ch[f[u]][c];
                else{
                    f[ch[u][c]]=ch[f[u]][c];
                    q.push(ch[u][c]);
                }
            }
        }
    }
    void find(char *s)
    {
        int u=rt,len=strlen(s);
        for(int i=0;i<len;i++){
            int c=s[i];
            u=ch[u][c];
            int t=u;
            while(t!=rt){
                for(int j=0;j<id[t].size();j++) ans.insert(id[t][j]);
                t=f[t];
            }
        }
    }
};
Trie ac;

int main()
{
    freopen("in.txt","r",stdin);
    while(cin>>N){
        ac.init();
        for(int i=1;i<=N;i++){
            scanf("%s",s);
            ac.insert(s,i);
        }
        ac.build();
        cin>>M;
        int cnt=0;
        for(int i=1;i<=M;i++){
            scanf("%s",s);
            ans.clear();
            ac.find(s);
            if((int)ans.size()>0){
                printf("web %d:",i);
                for(set<int>::iterator it=ans.begin();it!=ans.end();++it) printf(" %d",*it);
                puts("");
                cnt++;
            }
        }
        printf("total: %d\n",cnt);
    }
    return 0;
}
View Code

 

hdu3065:病毒侵袭持续中

很简单的题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>

using namespace std;

const int maxn=2000100;
const int N=1100;
const int maxm=500100;

char s[maxn];
int n;
char t[N][60];
int cnt[N];
struct Trie
{
    int ch[maxm][128],f[maxm];
    vector<int> id[maxm];
    int rt,L;
    int newnode()
    {
        memset(ch[L],-1,sizeof(ch[L]));
        id[L].clear();
        return L++;
    }
    void init()
    {
        for(int i=0;i<maxm;i++) id[i].clear();
        L=0;
        rt=newnode();
    }
    void insert(char *s,int ID)
    {
        int len=strlen(s),u=rt;
        for(int i=0;i<len;i++){
            int c=s[i];
            if(ch[u][c]==-1) ch[u][c]=newnode();
            u=ch[u][c];
        }
        id[u].push_back(ID);
    }
    void build()
    {
        queue<int> q;
        f[rt]=rt;
        for(int c=0;c<128;c++){
            if(ch[rt][c]==-1) ch[rt][c]=rt;
            else{
                f[ch[rt][c]]=rt;
                q.push(ch[rt][c]);
            }
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int c=0;c<128;c++){
                if(ch[u][c]==-1) ch[u][c]=ch[f[u]][c];
                else{
                    f[ch[u][c]]=ch[f[u]][c];
                    q.push(ch[u][c]);
                }
            }
        }
    }
    void find(char *s)
    {
        int len=strlen(s),u=rt;
        for(int i=0;i<len;i++){
            int c=s[i];
            u=ch[u][c];
            int t=u;
            while(t!=rt){
                for(int j=0;j<id[t].size();j++) cnt[id[t][j]]++;
                t=f[t];
            }
        }
    }
};
Trie ac;

int main()
{
    while(cin>>n){
        ac.init();
        for(int i=1;i<=n;i++){
            scanf("%s",t[i]);
            ac.insert(t[i],i);
        }
        ac.build();
        memset(cnt,0,sizeof(cnt));
        scanf("%s",s);
        ac.find(s);
        for(int i=1;i<=n;i++){
            if(cnt[i]){
                printf("%s: %d\n",t[i],cnt[i]);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2015-09-22 21:14  __560  阅读(198)  评论(0编辑  收藏  举报