HDU6096 String(Trie树)

HDU6096 String

Problem Description
Bob has a dictionary with N words in it.
Now there is a list of words in which the middle part of the word has continuous letters disappeared. The middle part does not include the first and last character.
We only know the prefix and suffix of each word, and the number of characters missing is uncertain, it could be 0. But the prefix and suffix of each word can not overlap.
For each word in the list, Bob wants to determine which word is in the dictionary by prefix and suffix.
There are probably many answers. You just have to figure out how many words may be the answer.

Input
The first line of the input gives the number of test cases T; T test cases follow.
Each test case contains two integer N and Q, The number of words in the dictionary, and the number of words in the list.
Next N line, each line has a string Wi, represents the ith word in the dictionary (0<|Wi|≤100000)
Next Q line, each line has two string Pi , Si, represents the prefix and suffix of the ith word in the list (0<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤100000)
All of the above characters are lowercase letters.
The dictionary does not contain the same words.

Limits
T≤5
0< N,Q≤100000
∑Si+Pi≤500000
∑Wi≤500000

Output
For each test case, output Q lines, an integer per line, represents the answer to each word in the list.

Sample Input
1
4 4
aba
cde
acdefa
cdef
a a
cd ef
ac a
ce f

Sample Output
2
1
1
0

Source
2017 Multi-University Training Contest – Team 6

这道题题解发的做法,跟本看不懂哇2333,反正比赛时把它a了,就当自己会做了吧。。。 题意是给n个字符串,然后m次查询,每次查询有给定的前缀和给定的后缀的字符串有多少个 对于每一个字符串构建字典树,但是不同于一般的构建,构建Trie树时,把每一个字符串的第1个字符放在第一个,第n-1个字符放在第二个,第2个字符放在第三个,n-2个字符放在第四个,以此类推,一共放进2n个字符,然后查询时,也把给定的前缀后缀如此处理,si,pn-1,s2,pn-2……如果前缀比后缀长或者后缀比前缀长就以特殊字符‘#’或者“*”替代,查询时则对所有的26个节点访问。 但是这样会有aaa aa aa输出为1的问题所以要先把所有的字符串和查询读入,然后对字符串根据字符串的长度排序,查询根据查询长度排序。这样在每次处理询问之前只把长度大于等于查询长度的字符串放进字典树中,就可以避开这个问题。 具体见代码,虽然代码略丑

#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define idx(x) x - 'a';
using namespace std;
const int MAXN = 3e6;
struct Trie {
    int next[26];
    int val;
}tree[MAXN];
int nxt, T;
char str[200005];
char ss[500005];
char s1[500005];
char s2[500005];
int ans;
struct xx
{
    int l,r;
}a[100005];
struct xxx
{
    int l,r,num,ll,rr;
}b[100005];
int anss[100005];
int add()
{
    memset(&tree[nxt], 0, sizeof(Trie));
    return nxt++;
}

void Insert(char *s)
{
    int rt = 0, len = strlen(s);
    for(int i = 0; i < len; i++) {
        int c = idx(s[i]);
        tree[rt].val++;
        if(!tree[rt].next[c]) {
            tree[rt].next[c] = add();
        }
        rt = tree[rt].next[c];
    }
    tree[rt].val++;
}

int cmp1(xx p,xx q)
{
    return(p.r-p.l)<(q.r-q.l);
}
int cmp2(xxx p,xxx q)
{
    return(p.r+p.rr-p.ll-p.l)<(q.rr+q.r-q.ll-q.l);
}
void cal(int i,int len,int now)
{
    if(i==len) {
        ans+=tree[now].val;
        return ;
    }
    if(str[i]=='#'){
        for(int j=0;j<26;j++){
            if(tree[now].next[j]) cal(i+1,len,tree[now].next[j]);

        }
    }
    else{
        if(tree[now].next[str[i]-'a'])
            cal(i+1,len,tree[now].next[str[i]-'a']);
    }

}
void init1(int x)
{
    int l=a[x].l,r=a[x].r;
    int summ=0;
    for(int j=l;j<r;j++){
        str[summ++]=ss[j];
        str[summ++]=ss[r-j+l-1];
    }
    str[summ]=0;
}
int init2(int x)
{
    int len1=b[x].r-b[x].l;
    int len2=b[x].rr-b[x].ll;
    int nn=max(len1,len2);
    int sum=0;
    for(int j=0;j<nn;j++){
        if(j<len1) str[sum++]=s1[j+b[x].l];
        else{
            str[sum++]='#';
        }
        if(len2-j-1>=0) str[sum++]=s2[b[x].rr-j-1];
        else{
            str[sum++]='#';
        }
    }
    str[sum]=0;
    ans=0;
    return sum;
}
int main()
{

    scanf("%d", &T);
    while(T--) {
        memset(&tree[0], 0, sizeof(Trie));
        nxt = 1;
        int n,m;
        scanf("%d %d",&n,&m);
        int sum=0;
        for(int i=0;i<n;i++){
            scanf("%s",ss+sum);
            a[i].l=sum;
            sum+=strlen(ss+sum);
            a[i].r=sum;
        }
        sort(a,a+n,cmp1);
        int sum1=0,sum2=0;
        for(int i=0;i<m;i++){
            scanf("%s %s",s1+sum1,s2+sum2);
            b[i].l=sum1;
            sum1+=strlen(s1+sum1);
            b[i].r=sum1;
            b[i].ll=sum2;
            sum2+=strlen(s2+sum2);
            b[i].rr=sum2;
            b[i].num=i;
        }

        sort(b,b+m,cmp2);
        int noww=n-1;
        for(int i=m-1;i>=0;i--){

            while(a[noww].r-a[noww].l>=b[i].rr+b[i].r-b[i].l-b[i].ll&&noww<n){
                init1(noww);
                noww--;

                Insert(str);
            }
            sum=init2(i);
            ans=0;
            cal(0,sum,0);
            anss[b[i].num]=ans;
        }
        for(int i=0;i<m;i++) printf("%d\n",anss[i]);
    }
    return 0;
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/Static_Ricardo/article/details/77072865
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞