[HDU 2222]Keywords Search[AC自动机]

题意:

多模式串匹配.

思路:

AC自动机,注意回溯.

优化fail建立过程.


#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 240055;
const int MAXL = 1000005;

struct AC_machine
{
    int fail[MAXN];
    int sz;
    int ch[MAXN][26];
    int ID[128];
    int n;
    char str[MAXL];
    int Q[MAXN];
    int v[MAXN];

    void Init()
    {
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(v,0,sizeof(v));
        fail[0] = 0;
        for(int i=0;i<26;i++)  ID[i+'a'] = i;
    }

    void Insert(char s[])
    {
        int cur = 0;
        for(int i=0;s[i];i++)
        {
            int c = ID[s[i]];
            if(!ch[cur][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                ch[cur][c] = sz++;
            }
            cur = ch[cur][c];
        }
        v[cur]++;
    }

    void Input()
    {

        scanf("%d",&n);
        char s[55];
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            Insert(s);
        }
        scanf("%s",str);
    }

    void Build()
    {
        int st = 0, en = 0;
        for(int i=0;i<26;i++)
        {
            if(ch[0][i])
            {
                fail[ch[0][i]] = 0;
                Q[en++] = ch[0][i];
            }
        }
        while(st!=en)
        {
            int cur = Q[st++];
            for(int i=0;i<26;i++)
            {
                int &v = ch[cur][i];
                if(v)
                {
                    Q[en++] = v;
                    fail[v] = ch[fail[cur]][i];
                }
                else
                {
                    v = ch[fail[cur]][i];//优化
                }
            }
        }
    }

    void solve()
    {
        int ans = 0,j = 0,tmp;
        for(int i=0;str[i];i++)
        {
            if(ch[j][ID[str[i]]])    j = ch[j][ID[str[i]]];
            else
            {
                while(j && !ch[j][ID[str[i]]])  j = fail[j];
                if(ch[j][ID[str[i]]])   j = ch[j][ID[str[i]]];
            }
            tmp = j;
            while(tmp && v[tmp])
            {
                ans += v[tmp];
                v[tmp] = 0;
                tmp = fail[tmp];
            }
        }
        printf("%d\n",ans);
    }
} AC;

int main()
{
    int T;
    scanf("%d",&T);

    while(T--)
    {
        AC.Init();
        AC.Input();
        AC.Build();
        AC.solve();
    }
}












你可能感兴趣的:([HDU 2222]Keywords Search[AC自动机])