Call from Mendes Gym - 102448C(字典樹)

Mendes, as you might already guess, is also a student from UFPE. He is known for having the worst ideas of all. So much that, when anyone gives a bad idea, it’s called a “call from Mendes”.

Tired of always falling for Mendes’ calls, his friends decided to study how he could know so many different bad ideas. They discovered Mendes has a dictionary of different words in his head, and that everytime he hears his friends say something, he would say the smallest word in length in his dictionary that has the given word as a prefix.

They also discovered that Mendes’ dictionary is not static. Sometimes, he gets new ideas from the internet and adds then to his dictionary. He also forgets some words, as they might not be funny anymore.

To check if their discoveries are correct, you were assigned to write a program that answers 3 types of queries:

1 X - Insert word X in the dictionary
2 X - Remove word with index X from the dictionary
3 X - Print the index of the word Mendes would say if he heard X. If there are multiple answers to a query, output the index of the lexicographically smallest word amongst them
Where the index of the word is the index of the query it was inserted in the dictionary (1-indexed)

Input
You will receive an integer Q (1<Q≤105), the number of queries, followed by Q lines of queries in the format specified above. It is guaranteed that every word in his dictionary is different at all times and that every query of type 2 is valid.

Output
The output must contain one line for each query of type 3. Each line should contain the index of the word Mendes would say to answer that query or −1 if Mendes does not have anything to say.

Example
Input
6
1 call
1 mendes
1 troll
3 mend
2 2
3 mendes
Output
2
-1
Note
Sum of lengths of strings in queries 1 and 3 will not exceed 106. Furthermore, all strings will consist only of lowercase Latin letters.

題意:
每次操作可以插入一個字符串,刪除一個字符串,或者詢問一個已有且字典序最小字符串爲所給字符串前綴。

思路:
亂搞了1天終於成功了,感覺400ms應該算是正解了吧XD。

就是維護一棵字典樹,然後這個字典樹的每一個節點維護一個set。
插入的時候就把這個字符串對應的大小序號插入到這個set裏面。
刪除的時候就刪除對應節點set裏面的字符串信息。
查詢的時候查詢字符串對應最後一個節點裏的set信息就是所要找的信息。

#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>

using namespace std;

const int maxn = 1e6 + 7;
string str[maxn];
int ch[maxn][26],OP[maxn],X[maxn];
int ID[maxn];

struct String {
    string now;
    int id;
    bool operator < (const String &rhs) const {
        if(now.length() == rhs.now.length()) return now < rhs.now;
        return now.length() < rhs.now.length();
    }
}STR[maxn];

struct Node {
    int last,len,pos;
    bool operator < (const Node &rhs) const {
        if(len == rhs.len) return ID[pos] < ID[rhs.pos];
        return len < rhs.len;
    }
};

multiset<Node>val[maxn];
int tot = 1;

void insert(string &a,int x,int y,int pos)
{
    int u = 1,len = a.length();
    for(int i = 0;i < len;i++)
    {
        int id = a[i] - 'a';
        if(!ch[u][id])
        {
            ch[u][id] = ++tot;
        }
        u = ch[u][id];
        val[u].insert({x,y,pos});
    }
}

int query(string &a)
{
    int ans = 0;
    int u = 1,len = a.length();
    for(int i = 0;i < len;i++)
    {
        int id = a[i] - 'a';
        if(!ch[u][id])
        {
            return -1;
        }
        u = ch[u][id];
    }
    if(val[u].size()) {
        return val[u].begin() -> pos;
    } else {
        return -1;
    }
}

void Delete(string &a,int x,int y,int pos) {
    int u = 1,len = a.size();
    for(int i = 0;i < len;i++)
    {
        int id = a[i] - 'a';
        if(!ch[u][id])
        {
            return;
        }
        u = ch[u][id];
        Node now; now.last = x; now.len = y; now.pos = pos;
        auto it = val[u].find(now);
        val[u].erase(it);
    }
}

int main() {
    ios::sync_with_stdio(false);
    int n;cin >> n;
    int cnt = 0;
    for(int i = 1;i <= n;i++) {
        cin >> OP[i];
        if(OP[i] == 2) {
            cin >> X[i];
        } else {
            cin >> str[i];
            STR[++cnt].now = str[i];
            STR[cnt].id = i;
        }
    }
    
    sort(STR + 1,STR + 1 + cnt);
    for(int i = 1;i <= cnt;i++) {
        ID[STR[i].id] = i;
    }
    
    for(int i = 1;i <= n;i++) {
        int op = OP[i];
        if(op == 1) {
            int len = str[i].length();
            insert(str[i],str[i][len - 1] - 'a',len,i);
        } else if(op == 2) {
            int x = X[i];
            int len = str[x].length();
            Delete(str[x], str[x][len - 1] - 'a',len,x);
        } else {
            string now = str[i];
            cout << query(now) << endl;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章