1. 程式人生 > >Trie樹【洛谷P3879】 [TJOI2010]閱讀理解

Trie樹【洛谷P3879】 [TJOI2010]閱讀理解

name urn getchar 都在 char 時間 lin turn 小寫

P3879 [TJOI2010]閱讀理解

題目描述

英語老師留了N篇閱讀理解作業,但是每篇英文短文都有很多生詞需要查字典,為了節約時間,現在要做個統計,算一算某些生詞都在哪幾篇短文中出現過。

輸入輸出格式

輸入格式:

第一行為整數N,表示短文篇數,其中每篇短文只含空格和小寫字母。

按下來的N行,每行描述一篇短文。每行的開頭是一個整數L,表示這篇短文由L個單詞組成。接下來是L個單詞,單詞之間用一個空格分隔。

然後為一個整數M,表示要做幾次詢問。後面有M行,每行表示一個要統計的生詞。

輸出格式:

對於每個生詞輸出一行,統計其在哪幾篇短文中出現過,並按從小到大輸出短文的序號,序號不應有重復,序號之間用一個空格隔開(註意第一個序號的前面和最後一個序號的後面不應有空格)。如果該單詞一直沒出現過,則輸出一個空行。

卡空間的毒瘤題。

怒開bitset過掉。

code:

#include <iostream>
#include <cstdio>
#include <bitset>

using namespace std;

const int wx=500017;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

int n,m;
char c[wx];

struct Trie{
    int tr[wx][29];
    bitset<1010>flag[wx];
    int cnt;
    
    void insert(char *s,int fl){
        int p=0;
        for(int i=0;s[i];i++){
            int k=s[i]-'a';
            if(!tr[p][k])tr[p][k]=++cnt;
            p=tr[p][k];
        }
        flag[p][fl]=1;
    }
    
    void query(char *s){
        int p=0;
        for(int i=0;s[i];i++){
            int k=s[i]-'a';
            if(!tr[p][k]){
                puts("");
                return ;
            }
            p=tr[p][k];
        }
        for(int i=1;i<=n;i++){
            if(flag[p][i])printf("%d ",i);
        }puts("");
    }
    
}Trie;

int main(){
    n=read();
    for(int i=1;i<=n;i++){
        int x; x=read();
        for(int j=1;j<=x;j++){
            scanf("%s",c);
            Trie.insert(c,i);
        }
    }
    m=read();
    for(int i=1;i<=m;i++){
        scanf("%s",c);
        Trie.query(c);
    }
    return 0;
}

Trie樹【洛谷P3879】 [TJOI2010]閱讀理解