您的位置:首页 > 其它

hdu2222,AC自动机,trie图

2016-05-28 00:59 141 查看
这题神坑啊。。主要有2个坑点

1.重复的不算,比如输入:

1

1

 he

hehe    一开始以为输出为2,,结果经过大量wa证明,输出是1

2输入中重复的词可以叠加,比如输入:

1

2

he

he

he  输出是2而不是1,,,,导致我wa了,,几十次。。

//2016年11月1日更新

嫌当初的代码风格太丑了,整理模板的时候,时隔半年又来重写了一下这道题

却发现这道题的数据不够严

比如

1

4

sher

he

say

her

sherhs

输出2,3都AC了,

正解应该是输出3把;

下面上AC自动机的代码(已更新):

#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<cstring>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define N 1111111
int n;
char s[1000000+10];
struct AC_trie
{
    int root,cnt;
    int End[500000+10],to[500000+10][27],fail[500000+10];//改
    int newnode()
    {
        for(int i=0; i<26; i++) to[cnt][i]=-1;
        End[cnt]=0;
        return cnt++;
    }
    void init()
    {
        cnt=0;
        root=newnode();
    }
    void insert(char *s)
    {
        int now=root;
        for(char *ss=s; *ss; ss++)
        {
            int v=*ss-'a';//改
            if(to[now][v]==-1)to[now][v]=newnode();
            now=to[now][v];
        }
        End[now]++;//改
    }
    void build()
    {
        queue<int> my;
        fail[root]=root;
        for(int i = 0; i < 26; i++)
            if(to[root][i] == -1)
                to[root][i]= root;
            else
            {
                fail[to[root][i]]=root;
                my.push(to[root][i]);
            }
        while(!my.empty())
        {
            int u=my.front();
            my.pop();
            for(int i=0; i<26; i++) //改
            {
                int v=to[u][i];
                if(v!=-1)
                {
                    fail[v]=to[fail[u]][i];
                    my.push(v);
                }
                else to[u][i]=to[fail[u]][i];
            }
        }
    }
    int query(char *s)
    {
        int ans=0;
        int now=root;
        for(char *ss=s; *ss; ss++)
        {
            int v=*ss-'a';
            now=to[now][v];
            int cur=now;
            while(cur!=root&&End[cur])//错误数据主要在这里,while(cur!=root)时输出为3,while(cur!=root&&End[cur])时输出为2,两者运行时间差4倍

            {
                ans+=End[cur];
                End[cur]=0;
                cur=fail[cur];
            }
        }
        return ans;
    }
} AC;
int main()
{
    FIN;
    int _;
    scanf("%d",&_);
    while(_--)
    {
        scanf("%d",&n);
        AC.init();
        for(int i=1; i<=n; i++)
        {
            scanf("%s",s);
            AC.insert(s);
        }
        AC.build();
        scanf("%s",s);
        printf("%d\n",AC.query(s));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: