【AC自动机】HDU 3695 Computer Virus on Planet Pandora 裸题

n个单词在一个字符串和该串的逆串出现了几个

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define cler(arr, val)    memset(arr, val, sizeof(arr))
#define IN     freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
const int MAXN = 1000006;//点数的最大值
const int MAXM = 20006;//边数的最大值
const int INF = 11521204;
const int mod=1000000007;
#define maxnode 250001
#define sigma_size 26
int ans;
struct Trie
{
    int ch[maxnode][sigma_size];
    int val[maxnode];    //该单词在模式串中出现的次数
    int last[maxnode];
    int f[maxnode];      //失配数组
    int num[maxnode];    //该单词出现在文本串的次数
    int pre[maxnode];    //该单词的前驱
    int len[maxnode];    //以该单词结尾的单词长度
    int Char[maxnode];   //该单词对应的字母
    int sz;
    void init()
    {
        sz=1;
        memset(ch,0,sizeof(ch));
        memset(val, 0, sizeof(val));
        memset(f,0,sizeof(f));
        memset(last,0,sizeof(last));    //记录该节点前一个节点是谁
        memset(len, 0, sizeof(len));
    }
    int idx(char c)
    {
        return c-'A';
    }
    int insert(char *s)
    {
        int u = 0;
        for(int i = 0; s[i] ; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])
                ch[u][c] = sz++;
            u = ch[u][c];
        }
        val[u] ++;
        return u;
    }
    void getFail()
    {
        queue<int> q;
        for(int i = 0; i<sigma_size; i++)
            if(ch[0][i]) q.push(ch[0][i]);

        while(!q.empty())
        {
            int r = q.front();
            q.pop();
            for(int c = 0; c<sigma_size; c++)
            {
                int u = ch[r][c];
                if(!u)continue;
                q.push(u);
                int v = f[r];
                while(v && ch[v][c] == 0)
                    v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
                f[u] = ch[v][c];
                last[u] = val[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
    void find(char *T)
    {
        int u = 0;
        for(int i = 0; T[i] ; i++)
        {
            int c = idx(T[i]);
            while(u && ch[u][c]==0)
                u = f[u];
            u = ch[u][c];
            int temp = u;
            while(temp && val[temp])  //沿失配边走 || 若沿失配边走时一定要节点为单词结尾则改成while(temp && val[temp])
            {
                ans+=val[temp];
                val[temp]=0;
                temp = f[temp];
            }
        }
        return ;
    }
} ac;
char s[5110000],s1[5110000];
int main()
{
    int t,n;
   // IN;
    scanf("%d",&t);
    while(t--)
    {
        ac.init();
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%s",s);
            ac.insert(s);
        }
        ac.getFail();
        int i=0;
        char c;
        getchar();
        while(c=getchar(),c>10)
        {
            if(c=='[')
            {
                int x;
                scanf("%d%c]",&x,&c);
                while(x--) s[i++]=c;
            }
            else
            {
                s[i++]=c;
            }
        }
        s[i]=s1[i]=0;
        for(int j=0;j<i;j++)
            s1[i-j-1]=s[j];
        ans=0;
        ac.find(s);ac.find(s1);
        printf("%d\n",ans);
    }
    return 0;
}


posted @ 2014-09-05 20:42  kewowlo  阅读(133)  评论(0编辑  收藏  举报