HDU 6096 String 字典樹數組建樹

題目鏈接:HDU6096

String

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 996    Accepted Submission(s): 325


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
T5
0<N,Q100000
Si+Pi500000
Wi500000
 

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
 

題意:

給出一堆單詞,然後m次查詢,每次給出前綴和後綴,詢問有幾個單詞滿足條件。

題目分析:

AC自動機的做法:把每個單詞的後綴放到前面然後在中間隔一個特殊字符,然後同樣處理查詢字符串,跑一遍ac自動機即可。

字典樹做法:前綴一個字母后綴一個交替的放入一個新字符串裏,然後錄入字典樹,查詢時同樣處理,然後如果不夠的話用特殊字符代替。查詢類似廣搜,然後不帶*的就1條路徑,帶*的就全錄進去(話說複雜度不會爆炸嗎)。當時賽場上想着是建立26*26的二維數組同時錄入前綴和後綴,然後考慮查詢最壞情況可能爆炸就沒寫完,這麼看還是可以試一試的,畢竟大同小異,一個是雙倍長度,一個是多26倍的節點。

//
//  main.cpp
//  HDU6096 String
//
//  Created by teddywang on 2017/8/14.
//  Copyright © 2017年 teddywang. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=2222222;
int n,q;
char s[N],t[N],st[N];
struct node{
    int L,root,net[N][26],ed[N];
    vector<int>G[N];
    int newnode()
    {
        for(int i=0;i<26;i++)
            net[L][i]=-1;
        ed[L]=0;
        return L++;
    }
    void init()
    {
        L=0;
        for(int i=0;i<N;i++)
            G[i].clear();
        root=newnode();
    }
    void build(char *s,int l)
    {
        int len=strlen(s);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int buf=s[i]-'a';
            if(net[now][buf]==-1)
            {
                net[now][buf]=newnode();
            }
            now=net[now][buf];
            G[now].push_back(l);
            ed[now]++;
        }
    }
    void dfs(int x)
    {
        sort(G[x].begin(),G[x].end());
        for(int i=0;i<26;i++)
        {
            if(net[x][i]!=-1)
            {
                dfs(net[x][i]);
            }
        }
    }
};
node trie;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        trie.init();
        scanf("%d%d",&n,&q);
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            int len=strlen(s);
            for(int j=0;j<len;j++)
            {
                st[j*2]=s[j];
                st[j*2+1]=s[len-1-j];
            }
            st[2*len]='\0';
            trie.build(st, len);
        }
        trie.dfs(0);
        for(int i=0;i<q;i++)
        {
            scanf("%s%s",s,t);
            int ls=strlen(s);
            int lt=strlen(t);
            int l=ls+lt;
            int ll=max(ls,lt);
            for(int j=0;j<ll;j++)
            {
                st[j*2]=j<ls?s[j]:'*';
                st[j*2+1]=j<lt?t[lt-1-j]:'*';
            }
            ll*=2;
            st[ll]='\0';
            queue<int> q[2];
            int tmp=0;
            q[0].push(0);
            int ans=0;
            for(int j=0;j<ll;j++)
            {
                tmp=1-tmp;
                int buf=st[j]-'a';
                while(!q[1-tmp].empty())
                {
                    int now=q[1-tmp].front();
                    q[1-tmp].pop();
                    if(st[j]=='*')
                    {
                        for(int k=0;k<26;k++)
                        {
                            if(trie.net[now][k]!=-1)
                                q[tmp].push(trie.net[now][k]);
                        }
                    }
                    else
                    {
                        if(trie.net[now][buf]!=-1)
                            q[tmp].push(trie.net[now][buf]);
                    }
                }
            }
            while(!q[tmp].empty())
            {
                int now=q[tmp].front();
                q[tmp].pop();
                int buf=lower_bound(trie.G[now].begin(), trie.G[now].end(),l)-trie.G[now].begin();
                ans-=buf;
                ans+=trie.ed[now];
                
            }
            printf("%d\n",ans);
        }
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章