中石油個人訓練 自動完成 APP(Tire樹 + dfs序優化)

題目描述

奶牛 Bessie 很喜歡用手機上網聊天,但她的蹄子太大,經常會按到好幾個鍵造成不必要的麻煩(丟死人了,你下輩子還是不要當奶牛了)。於是 Farmer John 給她專門設計了一套「自動完成 APP」。這個 APP 能夠連接到在線詞典來獲取詞庫(詞庫的來源是 Bessie 常用的 n 個單詞),並且有着自動補全的功能。當 Bessie 想打出她的一個常用單詞時,她只需輸入這個單詞的某個前綴,並詢問詞庫中擁有這個前綴的字典序第 k 小的單詞,APP 就會返回這是詞庫中的第幾個單詞。
Farmer John 是個大忙人,所以編寫 APP 的任務自然就交給了你。

 

輸入

第一行兩個整數 n,m,表示詞庫的單詞個數和 Bessie 的詢問次數。
接下來 n 行,每行一個字符串,表示 Bessie 的常用單詞,輸入的第 i 個字符串在詞庫中編號爲 i。
接下來 m 行,每行一個整數 k 和一個字符串 S,表示 Bessie 的詢問,意義是詢問詞庫中以 S 爲前綴的字典序第 k 小的單詞在詞庫中的編號。

 

輸出

對於每次詢問輸出一個整數,表示以S爲前綴的字典序第 k 小的單詞在詞庫中的編號;如果不存在這樣的單詞,輸出 −1。

 看到題,一股字典樹的套路感覺....於是敲了一個字典樹,可惜T了

後來看題解,發現對於第k小字典序,可以先dfs整顆字典樹,給每個串標號,然後在字典樹走完串後直接輸出下面的第k小即可.....

 

#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
const int maxn=1e6+7;
typedef long long ll;
const int mod=1e9+7;
//#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
#define IO cin.tie(0),ios::sync_with_stdio(false);
#define pi acos(-1)
#define PII pair<ll,ll>
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();if(c == '-')Nig = -1,c = getchar();while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();return Nig*x;}
#define read read()
/** keep hungry and keep calm! **/
 
struct node{
    int son[26],sz,end,id;
    int l,r;
}tire[maxn];
 
int tot = 1;
void ins(char *s,int id){
    int root = 1;
    tire[root].sz ++;
    for(int i=0;s[i];i++){
        int u = s[i] - 'a';
        if(tire[root].son[u] == 0){
            tire[root].son[u] = ++tot;
        }
        root = tire[root].son[u];
        tire[root].sz ++;
    }
    tire[root].end ++;
    tire[root].id = id;
}
 
int ans[maxn],cnt;
void dfs(int u){
    tire[u].l = cnt;
    if(tire[u].end){
        ans[cnt++] = tire[u].id;
    }
    for(int i=0;i<26;i++){
        if(tire[u].son[i]){
            dfs(tire[u].son[i]);
        }
    }
}
 
int solve(char *s,int k){
     
    int root = 1;
    for(int i=0;s[i];i++){
        int u = s[i] -'a';
        root = tire[root].son[u];
    }
    if(tire[root].sz < k) return -1;
    return ans[tire[root].l + k -1];
}
 
char s[maxn];
int Sheryang(){
     
    int n = read , Q = read;
     
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        ins(s,i);
    }
    dfs(1);
    while(Q--){
        int k = read;
        scanf("%s",s);
        printf("%d\n",solve(s,k));
    }
    return 0;
}

 

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