hihocoder 1261 String Problem II (Trie樹)

_TCgogogo_發表於2016-03-12
時間限制:50000ms
單點時限:5000ms
記憶體限制:512MB

描述

我們有一個字串集合S,其中有N個兩兩不同的字串。還有M個詢問,每個詢問都會先給出一個字串w,你需要回答以下三個問題:

1. 輸出所有S的串中,可以由w恰好新增兩個字元得到的串中,編號最小的3個。

2. 輸出所有S的串中,可以由w修改不超過2個字元得到的串中,編號最小的3個。

3. 輸出所有S的串中,可以由w刪除恰好兩個字元得到的串中,編號最小的3個。

字母可以新增在包括開頭結尾在內的任意位置,比如在"abc"中新增"x"和"y",可能可以得到"yxabc","aybxc","axbyc"等等的串。

所有字串只由小寫字母構成。

輸入

第一行兩個數N和M,表示集合S中字串的數量和詢問的數量。

接下來N行,其中第i行給出S中第i個字串。第i個字串的編號就是i。

接下來M行,其中第i行給出第i個詢問串。

資料範圍:

N,M<=10000。

S中字串長度和<=100000。

所有詢問中字串長度和<=100000。

輸出

對每個詢問輸出三行,每行三個數,分別表示每個問題編號最小的3個串的編號,從小到大排列。

如果不到3個串,則在最後用-1補到3個輸出,比如如果結果是1和2,那麼輸出1 2 -1,如果S中沒有滿足條件的串,就輸出-1 -1 -1。

樣例輸入
5 5
dsxmlkxp
asxglqkdxp
asxgavxp
asxglp
sxglkx
kebvpyky
hjpntqft
asxglkxp
polbmzgq
jdczlmtd
樣例輸出
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
2 -1 -1
1 3 -1
4 5 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1

題目連結:http://hihocoder.com/problemset/problem/1261

題目分析:是1260的擴充,正解應該是字串hash,Trie的複雜度理論會T,資料水了,Trie的思想和1260類似,就是在刪除和修改的地方轉移不同罷了,注意有個剪枝就是修改的時候如果列舉值和當前一樣則跳過

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int const MAX = 1e5 + 5;
int n, m, len;
char s[MAX];

struct Trie
{
    int next[MAX * 26][26], id[MAX * 26], tot, root, num, cou, res[5];
    set <int> ans; 
    set <int> :: iterator it;

    inline int Newnode()
    {
        memset(next[tot], -1, sizeof(next[tot]));
        return tot ++;
    }

    inline void Init()
    {
        tot = 0;
        root = Newnode();
    }

    inline void Clr()
    {
        cou = 0;
        ans.clear();
    }

    inline void Insert(char *s, int no)
    {
        int p = root;
        for(int i = 0; i < (int) strlen(s); i++)
        {
            int idx = s[i] - 'a';
            if(next[p][idx] == -1)
                next[p][idx] = Newnode();
            p = next[p][idx];
        }
        id[p] = no;
    }

    inline void DFS1(char *s, int pos, int p, int cnt)
    {
        if(id[p] && cnt == 0 && pos == len)
        {
            ans.insert(id[p]);
            return;
        }
        if(cnt > 0)
            for(int i = 0; i < 26; i++)
                if(next[p][i] != -1)
                    DFS1(s, pos, next[p][i], cnt - 1);
        if(pos == len)
            return;
        int idx = s[pos] - 'a';
        if(next[p][idx] != -1)
            DFS1(s, pos + 1, next[p][idx], cnt);
    }

    inline void DFS2(char *s, int pos, int p, int cnt)
    {
        if(id[p] && pos == len)
        {
            ans.insert(id[p]);
            return;
        }
        int idx = s[pos] - 'a';
        if(cnt > 0 && pos <= len)
            for(int i = 0; i < 26; i++)
                if(next[p][i] != -1 && i != idx)
                    DFS2(s, pos + 1, next[p][i], cnt - 1);
        if(pos == len)
            return;
        if(next[p][idx] != -1)
            DFS2(s, pos + 1, next[p][idx], cnt);
    }

    inline void DFS3(char *s, int pos, int p, int cnt)
    {
        if(id[p] && pos == len && cnt == 0)
        {
            ans.insert(id[p]);
            return;
        }
        if(cnt > 0)
            DFS3(s, pos + 1, p, cnt - 1);
        if(pos == len)
            return;
        int idx = s[pos] - 'a';
        if(next[p][idx] != -1)
            DFS3(s, pos + 1, next[p][idx], cnt);
    }

    inline void Output()
    {
        for(it = ans.begin(); it != ans.end() && cou != 3; it++)
            res[cou ++] = *it;
        for(int i = cou; i < 3; i++)
            res[i] = -1;
        printf("%d %d %d\n", res[0], res[1], res[2]);
    }

}t;

int main()
{
    t.Init();
    scanf("%d %d", &n, &m);
    for(int i = 0; i < n; i++)
    {
        scanf("%s", s);
        t.Insert(s, i + 1);
    }
    for(int i = 0; i < m; i++)
    {
        scanf("%s", s);
        len = strlen(s);
        t.Clr();
        t.DFS1(s, 0, t.root, 2);
        t.Output();

        t.Clr();
        t.DFS2(s, 0, t.root, 2);
        t.Output();
        
        t.Clr();
        t.DFS3(s, 0, t.root, 2);
        t.Output();
    }
}

相關文章