[AC自动机]HDOJ3695 Computer Virus on Planet Pandora

题意:给t、n,t个案例,n个字符串

  下面给n+1个字符串,n个互不相同的小串,最后一个是模式串

  模式串会出现[qx]的形式,q为数字,x为一个字母

问n个小串在模式串中出现的个数,正着出现、反着出现都算。

蛮裸的ac自动机,本来想着在query里面把找到过的end清零,把模式串展开正着反着找两遍,那即使再找到加零也不影响。但是超时了。。。

于是把找到过的end标为-1,-1了就不再找下去,就可以了~上代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cctype>
#include <cmath>
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iomanip>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
typedef long long LL;
typedef long double LD;
const double eps=1e-8;
#define pi acos(-1.0)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
typedef pair<int, int> PI;
typedef pair<int, PI> PP;
#ifdef _WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}
//inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}
//inline void print(LL x){printf(LLD, x);puts("");}
//inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}}
//inline void sc(LL &x){scanf(LLD, &x);}

struct Trie
{
    int next[5000100][26], fail[5000100], end[5000100];
    int root, L;
    int newnode()
    {
        for(int i=0;i<26;i++)
            next[L][i]=-1;
        end[L++]=0;
        return L-1;
    }
    void init()
    {
        L=0;
        root=newnode();
    }
    void insert(char buf[])
    {
        int len=strlen(buf);
        int now=root;
        for(int i=0;i<len;i++)
        {
            if(next[now][buf[i]-'A']==-1)
                next[now][buf[i]-'A']=newnode();
            now=next[now][buf[i]-'A'];
        }
        end[now]++;
    }
    void build()
    {
        queue<int> Q;
        fail[root]=root;
        for(int i=0;i<26;i++)
        if(next[root][i]==-1)
            next[root][i]=root;
        else
        {
            fail[next[root][i]]=root;
            Q.push(next[root][i]);
        }
        while(!Q.empty())
        {
            int now=Q.front();
            Q.pop();
            for(int i=0;i<26;i++)
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    Q.push(next[now][i]);
                }
        }
    }
    int query(char buf[])
    {
        int len=strlen(buf);
        int now=root;
        int res=0;
        for(int i=0;i<len;i++)
        {
            now=next[now][buf[i]-'A'];
            int tmp=now;
            while(tmp!=root && end[tmp]!=-1)
            {
                res+=end[tmp];         //printf("%d %d
", tmp, end[tmp]);
                end[tmp]=-1;
                tmp=fail[tmp];
            }
        }
        return res;
    }
}ac;
char buf[5200010], tmp[5200010];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        ac.init();
        for(int i=0;i<n;i++)
        {
            scanf("%s", buf);
            ac.insert(buf);
//            int LEN=strlen(buf);
//            reverse(buf, buf+LEN);
//            ac.insert(buf);
        }
        ac.build();
        scanf("%s", tmp);
        int LEN=strlen(tmp), d=0;
        for(int i=0;i<LEN;i++)
            if(tmp[i]=='[')
            {
                int cur=i+1, num=0;
                while(isdigit(tmp[cur]))
                    num=num*10+tmp[cur++]-'0';
                fill(buf+d, buf+d+num, tmp[cur]);
                i=cur+1, d+=num;
            }
            else
                buf[d++]=tmp[i];
        buf[d]='';
//        puts(buf);
//        for(int i=0;i<ac.L;i++)
//            printf("%d %d
", i, ac.end[i]);
        int ans=ac.query(buf);
        reverse(buf, buf+d);
        printf("%d
", ans+ac.query(buf));
    }
    return 0;
}
HDOJ 3695
原文地址:https://www.cnblogs.com/Empress/p/4119869.html