hdu6096(字典树)

来源:互联网 发布:zdm cad辅助设计软件 编辑:程序博客网 时间:2024/06/10 01:47

题意是给n个字符串,然后m次查询,每次查询有给定的前缀和给定的后缀的字符串有多少个 对于每一个字符串构建字典树,但是不同于一般的构建,构建Trie树时,把每一个字符串的第1个字符放在第一个,第n-1个字符放在第二个,第2个字符放在第三个,n-2个字符放在第四个,以此类推,一共放进2n个字符,然后查询时,也把给定的前缀后缀如此处理,si,pn-1,s2,pn-2……如果前缀比后缀长或者后缀比前缀长就以特殊字符‘#’或者“*”替代,查询时则对所有的26个节点访问。 但是这样会有aaa aa aa输出为1的问题所以要先把所有的字符串和查询读入,然后对字符串根据字符串的长度排序,查询根据查询长度排序。这样在每次处理询问之前只把长度大于等于查询长度的字符串放进字典树中,就可以避开这个问题。

自己写的错误百出,最后总算a了,注意指针越界,不然会runtime errro

#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <cmath>

#include <map>

#include <cstdlib>

using namespacestd;

char str[500005],s1[500005],s2[500005];

char nstr[500005],qstr[500005];

int ssm[500005],num;

struct nnode

{

    int l,r;

}a[100005];

struct qnode

{

    int r,l,rr,ll,sum;

}b[100005];

struct node

{

    int flag;

    node *next[26];

}*root;

bool cmp1(nnode a,nnode b)

{

    return (a.r-a.l)<(b.r-b.l);

}

bool cmp2(qnode a,qnode b)

{

    return (a.r-a.l+a.rr-a.ll)<(b.r-b.l+b.rr-b.ll);

}

node *build()

{

    node *p = (node *)malloc(sizeof(node));

    for(int i =0; i <26; i ++)

        p -> next[i] =NULL;

    p -> flag =0;

    return p;

}

void save(char *s)

{

    node *p;

    p = root;

    int len =strlen(s);

    for(int i =0; i < len; i ++)

    {

        if(p ->next[s[i] -'a'] ==NULL)

            p -> next[s[i] -'a'] =build();

        p->next[s[i]-'a']->flag++;

        p = p -> next[s[i] -'a'];

    }

}

void query(node *p,int i,int len)

{

    if(i==len)

    {

        num+=p->flag;

        return;

    }

    if(qstr[i]=='*')

    {

        for(int k =0; k <26; k ++)

        {

            if(p->next[k]!=NULL)

            {

                query(p->next[k],i+1,len);

            }

        }

    }

    else

    {

        if(p->next[qstr[i]-'a']!=NULL)

        {

            query(p->next[qstr[i]-'a'],i+1,len);

        }

    }

}

void init_n(int j)

{

    int k=0;

    for(int i=a[j].l;i<a[j].r;i++)

    {

        nstr[k++]=str[i];

        nstr[k++]=str[a[j].r-(i-a[j].l)-1];

    }

    nstr[k]=0;

}

void init_q(int j)

{

    int len=max(b[j].r-b[j].l,b[j].rr-b[j].ll);

    int l=b[j].l,ll=b[j].rr-1;

    int k=0;

    for(int i=0;i<len;i++)

    {

        if(l<b[j].r)

            qstr[k++]=s1[l++];

        else

            qstr[k++]='*';

        

        if(ll>=b[j].ll)

            qstr[k++]=s2[ll--];

        else

            qstr[k++]='*';

    }

    qstr[k]=0;

}

int main()

{

    

    int n,t,q;

    cin>>t;

    while(t--)

    {

        root =build();

        scanf("%d %d",&n,&q);

        int sum=0;

        for(int i=0;i<n;i++)

        {

            scanf("%s",str+sum);

            a[i].l=sum;

            sum+=strlen(str+sum);

            a[i].r=sum;

        }

        //printf("%s\n",str);

        sort(a,a+n,cmp1);

        int sum1=0,sum2=0;

        for(int i=0;i<q;i++)

        {

            b[i].l=sum1;

            b[i].ll=sum2;

            scanf("%s %s",s1+sum1,s2+sum2);

            sum1+=strlen(s1+sum1);

            sum2+=strlen(s2+sum2);

            b[i].r=sum1;

            b[i].rr=sum2;

            b[i].sum=i;

        }

        sort(b,b+q,cmp2);

        int j=n-1;

        memset(ssm,0,sizeof(ssm));

        for(int i=q-1;i>=0;i--)

        {

            while(b[i].r-b[i].l+b[i].rr-b[i].ll<=a[j].r-a[j].l&&j>=0)

            {

                init_n(j);

                save(nstr);

                j--;

            }

            init_q(i);

            node *p;

            p = root;

            int len =strlen(qstr);

            num=0;

            query(p,0,len);

            ssm[b[i].sum]=num;

        }

        for(int ii=0;ii<q;ii++)

            printf("%d\n",ssm[ii]);

    }

    return0;

}


/***********************

唉真难啊,这道题写了一个下午加一个晚上,各种错,交了n次,感觉自己好笨

原创粉丝点击