HDU2222:Keywords Search——题解

http://acm.hdu.edu.cn/showproblem.php?pid=2222

题目大意:

给定 n 个长度不超过 50 的由小写英文字母组成的单词,以及一篇长为 m 的文章,问有多少个单词在文章中出现了,多组数据。

——————————————————————

AC自动机裸题。

(C++AC,G++TLE我能说什么……)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int N=1e4+3;
const int M=1e6+3;
const int L=50+3;
struct trie{
    int ed;
    int a[26];
    int fail;
    void clear(){
    ed=fail=0;
    memset(a,0,sizeof(a));
    return;
    }
}tree[N*L]={0};
char s[M];
int cnt=0;
inline void insert(){
    int now=0;
    int len=strlen(s);
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        if(!tree[now].a[t]){
            cnt++;
            tree[now].a[t]=cnt;
        tree[cnt].clear();
        }
        now=tree[now].a[t];
    }
    tree[now].ed++;
    return;
}
int q[N*L];
void getfail(){
    int r=0;
    //以下是对第一层的特殊处理 
    for(int i=0;i<26;i++){
        if(tree[0].a[i]!=0){
            tree[tree[0].a[i]].fail=0;
        r++;q[r]=tree[0].a[i];
        }
    }
    for(int l=1;l<=r;l++){
        int u=q[l];
        for(int i=0;i<26;i++){
            if(tree[u].a[i]!=0){
                tree[tree[u].a[i]].fail=tree[tree[u].fail].a[i];
        r++;q[r]=tree[u].a[i];
            }else{
                tree[u].a[i]=tree[tree[u].fail].a[i];
            }
        }
    }
    return;
}
int check(){
    int now=0,ans=0;
    int len=strlen(s);
    for(int i=0;i<len;i++){
        int t=s[i]-97;
        now=tree[now].a[t];
        for(int j=now;j&&tree[j].ed!=-1;j=tree[j].fail){
            ans+=tree[j].ed;
            tree[j].ed=-1;
        }
    }
    return ans;
}
int main(){
    int t;
    cin>>t;
    while(t--){
    tree[0].clear();
    cnt=0;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        insert();
    }
    getfail();
    cin>>s;
    cout<<check()<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luyouqi233/p/7987521.html