首页 > 其他 > 详细

hdu 2222 Keywords Search

时间:2018-08-20 00:06:42      阅读:198      评论:0      收藏:0      [点我收藏+]

题目大意:

给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词。

解题分析:

这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非常多的时候,耗时会非常多,所以这里用到了AC自动机,这是一种类似于Trie树的数据结构,但是同时,它也用到了KMP算法中 next数组的思想。

下面是AC自动机指针形式的题解:

#include <iostream>
#include <cstring>
#include <string.h>
#include <algorithm>
using namespace std;

const int N =10000*50+10;
struct node {
    int cnt;
    node *fail;
    node *next[26];
    node() {
        cnt=0;
        fail=NULL;
        for(int i=0;i<26;i++) next[i]=NULL;
    }
}*que[N];   node *root;

void ins(char *s) {
    int len = strlen(s);
    node *tmp,*rt=root;
    for(int i=0;i<len;i++) {
        int id=s[i]-a;
        if(rt->next[id]==NULL)
            rt->next[id]=new node();
        rt=rt->next[id];
    }
    rt->cnt++;
}

void build_AC() {
    int st=0,ed=0;
    que[ed++]=root;
    while (st < ed) {
        node *tmp, *rt=que[st++];
        for(int i=0;i<26;i++) {
            if(rt->next[i]!=NULL) {
                if(rt==root)
                    //单个字符,没有后缀,因此失配指向root
                    rt->next[i]->fail=root;
                else {
                    //不断找父亲的fail指针下面有next[id]的后缀
                    tmp = rt->fail;
                    while (tmp!=NULL) {
                        if(tmp->next[i]!=NULL) {
                            rt->next[i]->fail = tmp->next[i];
                            break;
                        }
                        tmp=tmp->fail;
                    }
                    if(tmp==NULL)
                        rt->next[i]->fail=root;
                }
                que[ed++]=rt->next[i];
            }
        }
    }
}

int match(char *s) {
    node *rt=root;
    int len=strlen(s);
    int res=0;
    for(int i=0;i<len;i++) {
        int id= s[i]-a;
        if(rt->next[id]!=NULL) rt=rt->next[id];
        else {
            rt=rt->fail;
            while (rt!=NULL && rt->next[id]==NULL) rt=rt->fail;
            if(rt != NULL) rt=rt->next[id];
            else rt=root;
        }
        node *tmp = rt;
        if(tmp->cnt > 0) {
            while (tmp!=NULL) {
                res += tmp->cnt;
                tmp->cnt=0;
                tmp = tmp->fail;
            }
        }
    }
    return res;
}
int T,n; char word[1000000+10],str[60];

int main () {
    scanf("%d",&T);
    while (T--) {
        root=new node();
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%s",str),ins(str);
        build_AC();
        scanf("%s",word); printf("%d\n",match(word));
    }
    return 0;
}

参考blog/资料:

  https://www.bilibili.com/video/av6295004

  https://www.cnblogs.com/00isok/p/9426990.html

hdu 2222 Keywords Search

原文:https://www.cnblogs.com/Draymonder/p/9503316.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!