hdu 2896 病毒侵袭 ac自动机

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896

题意:有N(1<=N<=500)个模板串,每个模板串的长度n <= 200;之后有M(1<=M <= 1000)个文本串,每个文本串的长度len <= 10000;问有多少个模板串出现在输入的文本串中,按照模板串的顺序排序输出;

思路:ac自动机裸题。。

坑点:字符的为可行的ASCII码,即sigma_size = 128;并且还是idx好用,之后直接改即可;好几发都是写s[i] - 'a'..醉了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
#define pb push_back
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
int T,kase = 1,i,j,k,n,m;
const int sigma_size = 128;//**
const int maxn = 200*500+7;
struct Aho_Corasick{
    int ch[maxn][sigma_size];
    int val[maxn],f[maxn],last[maxn],cnt[maxn];
    int sz;
    map<string,int> ms;
    vector<int> vec;
    Aho_Corasick(){}
    void init(){sz = 1; MS0(ch[0]);MS0(cnt);ms.clear();}
    int idx(char c){return c;}
    void Insert(char *s,int v){
        int u = 0,n = strlen(s);
        for(int i = 0;i < n;i++){
            int c = idx(s[i]);
            if(!ch[u][c]){
                MS0(ch[sz]);
                val[sz] = 0;
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
        val[u] = v;
        ms[string(s)] = v;
    }
    void getFail(){
        queue<int> q;
        f[0] = 0;
        //初始化队列
        for(int c = 0;c < sigma_size;c++){
            int u = ch[0][c];
            if(u) { f[u] = 0; q.push(u); last[u] = 0;}
        }
        while(!q.empty()){
            int r = q.front();q.pop();
            for(int c = 0;c < sigma_size;c++){
                int u = ch[r][c];
                if(!u) {ch[r][c] = ch[f[r]][c]; continue;}//实现压缩
                q.push(u);
                int v = f[r];
                while(v && !ch[v][c]) v = f[v];
                f[u] = ch[v][c];
                last[u] = val[f[u]]?f[u]:last[f[u]];
            }
        }
    }
    //从文本串中找模板;
    void Find(char *T){
        int n = strlen(T);
        int j = 0;
        for(int i = 0;i < n;i++){
            int c = idx(T[i]);
            j = ch[j][c];//直接查找即可;
            if(val[j]) print(j);
            else if(last[j]) print(last[j]);
        }
    }
    void print(int j){
        if(j) {
            vec.pb(val[j]);
            print(last[j]);
        }
    }
}ac;
char p[255];
char text[10007];
int main()
{
    while(scanf("%d",&n) == 1){
        ac.init();
        rep1(i,1,n){
            scanf("%s",p);
            ac.Insert(p,i);
        }
        ac.getFail();
        int tot = 0;
        read1(m);
        rep1(k,1,m){
            scanf("%s",text);
            ac.Find(text);
            int sz = ac.vec.size();
            if(sz){
                tot++;
                printf("web %d:",k);
                sort(ac.vec.begin(),ac.vec.end());
                sz = unique(ac.vec.begin(),ac.vec.end())-ac.vec.begin();
                rep0(i,0,sz){
                    putchar(' ');
                    out(ac.vec[i]);
                }
                puts("");
            }
            ac.vec.clear();
        }
        printf("total: %d
",tot);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hxer/p/5331088.html