HDU2222 (ac自动机)(模板)

202ms

#include<bits/stdc++.h>

using namespace std;

const int N=5e5+10;

struct AC_Automaton{
    int next[N][26];
    int fail[N];
    int cnt[N];
    int root,tot;
    int newnode(){
        for(int i=0;i<26;i++){
            next[tot][i]=-1;
        }
        fail[tot]=-1;
        cnt[tot]=0;
        return tot++;
    }
    void clear(){
        tot=0;
        root=newnode();
    }
    void insert(const string &s){
        int p=root;
        for(int i=0,len=s.length();i<len;i++){
            if(next[p][s[i]-'a']==-1){
                next[p][s[i]-'a']=newnode();
            }
            p=next[p][s[i]-'a'];
        }
        cnt[p]++;
    }
    void build(){
        queue<int> q;
        q.push(root);
        while(!q.empty()){
            int p=q.front();q.pop();
            for(int i=0;i<26;i++){
                if(~next[p][i]){
                    if(p==root) fail[next[p][i]]=root;
                    else fail[next[p][i]]=next[fail[p]][i];
                    q.push(next[p][i]);
                }else{
                    if(p==root) next[p][i]=root;
                    else next[p][i]=next[fail[p]][i];
                }
            }
        }
    }
    int solve(const string &t){
        int p=root,ans=0;
        for(int i=0,len=t.length();i<len;i++){
            p=next[p][t[i]-'a'];
            for(int tmp=p;tmp!=root&&cnt[tmp]!=-1;tmp=fail[tmp]){
                ans+=cnt[tmp];
                cnt[tmp]=-1;
            }
        }
        return ans;
    }
}ac;

int main(){
    cin.sync_with_stdio(0);
    int cs;
    cin>>cs;
    while(cs--){
        ac.clear();
        int n;cin>>n;
        for(int i=0;i<n;i++){
            string s; cin>>s;
            ac.insert(s);
        }
        ac.build();
        string t;
        cin>>t;
        cout<<ac.solve(t)<<endl;
    }
    return 0;
}

889ms 计蒜客标程

#include <iostream>
#include<cstring>

using namespace std;

const int MAX_N = 5e5+10;
const int MAX_C = 26;

struct AC_Automaton{
    int ch[MAX_N][MAX_C],fail[MAX_N],cnt[MAX_N];// ch 和 cnt 数组与 Trie 树中的一样;fail 保存的是失败指针。ch 和 fail 默认都为 -1
    int tot;  // Trie 树的总结点(不含根结点)个数

    void init(){
        memset(ch,-1,sizeof(ch));
        memset(fail,0,sizeof(fail));
        tot=0;
        memset(cnt,0,sizeof(cnt));
    }

    void insert(char *str){
        int p=0;
        for(int i=0;str[i];i++){
            if(ch[p][str[i]-'a']==-1){
                ch[p][str[i]-'a']=++tot;
            }
            p=ch[p][str[i]-'a'];
        }
        cnt[p]++;
    }

    void build(){
        int l=0,r=0,Q[MAX_N];
        for(int i=0;i<MAX_C;i++){
            if(ch[0][i]==-1){
                ch[0][i]=0;
            }else{
                Q[r++]=ch[0][i];
            }
        }
        while(l<r){
            int p=Q[l++];
            for(int i=0;i<MAX_C;i++){
                if(ch[p][i]==-1){
                    ch[p][i]=ch[fail[p]][i];
                }else{
                    fail[ch[p][i]]=ch[fail[p]][i];
                    Q[r++]=ch[p][i];
                }
            }
        }
    }

    int count(char *str){ // 统计字符串集合(Trie)中在给定的一个字符串出现了多少次
        int ret=0,p=0;
        for(int i=0;str[i];i++){
            p=ch[p][str[i]-'a'];
            int tmp=p;
            while(tmp){
                ret+=cnt[tmp];
                cnt[tmp]=0; // 避免重复统计同一字符串
                tmp=fail[tmp];
            }
        }
        return ret;
    }

}ac;

char s[1000006];

int main() {
	int cs;
	scanf("%d",&cs);
	int n;
	while(cs--){
        ac.init();
        scanf("%d",&n);
        while(n--){
            scanf("%s",s);
            ac.insert(s);
        }
        ac.build();
        scanf("%s",s);
        printf("%d\n",ac.count(s));
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值