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

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

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

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

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

 

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

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

 

[AC自动机]HDOJ3695 Computer Virus on Planet Pandora
#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\n", 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]='\0';

//        puts(buf);

//        for(int i=0;i<ac.L;i++)

//            printf("%d %d\n", i, ac.end[i]);

        int ans=ac.query(buf);

        reverse(buf, buf+d);

        printf("%d\n", ans+ac.query(buf));

    }

    return 0;

}
HDOJ 3695

 

你可能感兴趣的:(AC自动机)