HDU 3695 浅谈AC自动机模式串匹配算法+严格空间控制

来源:互联网 发布:2016网络彩票重启时间 编辑:程序博客网 时间:2024/06/07 08:41

这里写图片描述
世界真的很大
日常被数组坑233
感觉怎么也调不出来的时候就去看一下是不是空间的问题吧。。
HDU的题日常多组数据。。
每组数据用完不清零基本上MLE

看题先:

description:

给出很多个模式串,问在文章里有几个模式串,(反过来的模式串也算)出现过文章里有时会有形如[n X]的东西,n是数字,X是字符,表示这个位置有nX字符n不一定是一位数

input:

多组数据,每组数据开头一个数字n,表示有n个模式串接下来n行,每行一个模式串然后一个字符串给出文章

output:

每组数据一个数字表示有都是个模式串出现过

基本上还算是AC自动机的裸题,为了复习AC自动机的写法去做的,却意外的调了半天,忽然觉得还是写一下比较好

首先考虑怎么处理模式串反过来也算的问题
就直接反过来再插入就好
但是这两个串都出现也只能算一个串出现了,所以考虑给trie树里面每个串打标记,标记其属于哪个模式串

然后处理文章里面[]的问题。
还是比较简单,注意一下细节就好

数组记得开大一点,字符串开5100010
我就是数组开小了,WA了半天。。他不RE,WA。。

完整代码:

#include<stdio.h>#include<cstring>#include<queue>#include<algorithm>using namespace std;struct node{    node *fail;    node *nxt[26];    int cnt,mrk,idc;}pool[10000010],*tail=pool,*root;int n,T,vis[8000010];char t[5100010],ss[5100010],sss[5100010];node *newnode(){    node *nd=++tail;    memset(nd->nxt,0,sizeof(nd->nxt));    nd->fail=0;    nd->cnt=nd->mrk=nd->idc=0;    return nd;}void init(){    memset(ss,0,sizeof(ss));    memset(t,0,sizeof(t));    memset(sss,0,sizeof(sss));    memset(vis,0,sizeof(vis));    tail=pool;    root=newnode();}void insert(char *s,int id){    int len=strlen(s);    node *p=root;    for(int i=0;i<len;i++)    {        int k=s[i]-'A';        if(!p->nxt[k])            p->nxt[k]=newnode();        p=p->nxt[k];    }    p->cnt++;    p->idc=id;}void build(){    queue <node*> state;    state.push(root);    root->fail=0;    while(!state.empty())    {        node *tmp=state.front(),*p=0;        state.pop();        for(int i=0;i<26;i++)            if(tmp->nxt[i])            {                if(tmp==root) tmp->nxt[i]->fail=root;                else                {                    p=tmp->fail;                    while(p)                    {                        if(p->nxt[i])                        {                            tmp->nxt[i]->fail=p->nxt[i];                            break ;                        }                        p=p->fail;                    }                    if(!p) tmp->nxt[i]->fail=root;                }                state.push(tmp->nxt[i]);            }    }}void trans(char *s){    int i;    int j=0,num=0;    for(i=0;s[i];i++){        if('A'<=s[i] && s[i]<='Z')          ss[j++] = s[i];        else if( '0'<=s[i] && s[i]<='9')            num = num*10 + int(s[i]-'0');        else if( s[i]==']' )            while(--num)                ss[j++] = s[i-1];    }    ss[j] = '\0';}void query(char *s){    int cnt=0,k,len=strlen(s);    node *p=root;    for(int i=0;i<len;i++)    {        k=s[i]-'A';        while(!p->nxt[k] && p!=root) p=p->fail;        p=p->nxt[k];        if(!p) p=root;        node *tmp=p;        while(tmp!=root&& !tmp->mrk)        {            tmp->mrk=1;            if(tmp->idc>0) vis[tmp->idc]=1;            tmp=tmp->fail;        }    }}int getans(){    int rt=0;    for(int i=1;i<=n;i++)        rt+=vis[i];    return rt;}int main(){    scanf("%d",&T);    while(T--)    {        init();        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%s",t);            insert(t,i);            reverse(t,t+strlen(t));            insert(t,i);        }        build();        scanf("%s",sss);        trans(sss);query(ss);        printf("%d\n",getans());    }    return 0;}/*Whoso pulleth out this sword from this stone and anvil is duly born King of all England*/

嗯,就是这样

原创粉丝点击