洛谷[3879] [TJOI2010]阅读理解(trie树模板)

题目链接:luogu3879


P3879 [TJOI2010]阅读理解

时空限制 2s / 128MB


题目描述

英语老师留了N篇阅读理解作业,但是每篇英文短文都有很多生词需要查字典,为了节约时间,现在要做个统计,算一算某些生词都在哪几篇短文中出现过。

输入输出格式

输入格式:

第一行为整数N,表示短文篇数,其中每篇短文只含空格和小写字母。
按下来的N行,每行描述一篇短文。每行的开头是一个整数L,表示这篇短文由L个单词组成。接下来是L个单词,单词之间用一个空格分隔。
然后为一个整数M,表示要做几次询问。后面有M行,每行表示一个要统计的生词。

输出格式:

对于每个生词输出一行,统计其在哪几篇短文中出现过,并按从小到大输出短文的序号,序号不应有重复,序号之间用一个空格隔开(注意第一个序号的前面和最后一个序号的后面不应有空格)。如果该单词一直没出现过,则输出一个空行。

输入输出样例

输入样例#1:

3
9 you are a good boy ha ha o yeah
13 o my god you like bleach naruto one piece and so do i
11 but i do not think you will get all the points
5
you
i
o
all
naruto

输出样例#1:

1 2 3
2 3
1 2
3
2

说明

对于30%的数据,1 ≤ M ≤ 1,000
对于100%的数据,1 ≤ M ≤ 10,000,1 ≤ N ≤ 100

每篇短文长度(含相邻单词之间的空格) ≤ 5,000 字符,每个单词长度 ≤ 20 字符

每个测试点时限2秒

题解 :
这道题,本来第一眼看过去是用trie树来写的。但是看了一下数据范围就直接开了map暴力跑了过去。当然用trie来练练手也是可以的。大概就是模拟这么一个过程,将所有的单词在哪篇文章出现过都存起来,直接输出需要询问的单词,但如果是没有出现过还要注意输出空行

代码(map):

#include
#include
#include
#include
#include
using namespace std;
#define ll long long
inline int read(){
    int x = 0,f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x*10+ch-'0'; ch = getchar();}
    return x*f;
}

map<string,int> mp;
int heap[500000][101];
int top[500000];
int n,m,cnt;

int main(){
    n = read(); string s;
    for(int i = 1;i <= n;i++){
        int l = read();
        for(int j = 1;j <= l;j++){
            cin>>s;
            if(mp[s] == 0) mp[s] = ++cnt;
            int x = mp[s];
            if(heap[x][top[x]] == i) continue;
            heap[x][++top[x]] = i;
        }
    }
    m = read();
    for(int i = 1;i <= m;i++){
        cin>>s;
        int x = mp[s];
        if(top[x] == 0) puts("");
        else{
            for(int i = 1;i < top[x];i++)
                printf("%d ",heap[x][i]);
            printf("%d\n",heap[x][top[x]]);     
        }
    }
    return 0;
}

代码(trie):

#include
#include
#include
#include
using namespace std;
#define ll long long
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int tri[26][5000001];
bool show[101][5000001];
int n,cnt;

void insert(int x){
    char s[25];
    scanf("%s",s);
    int len = strlen(s);
    int now = 0;
    for(int i = 0;i < len;i++){
        if(tri[s[i]-'a'][now] == 0) tri[s[i]-'a'][now] = ++cnt;
        now = tri[s[i]-'a'][now];
    }
    show[x][now] = true;
}

void check(){
    char s[25];
    scanf("%s",s);
    bool flag = true;
    int len = strlen(s);
    int now = 0;
    for(int i = 0;i < len;i++){
        if(tri[s[i]-'a'][now] == 0){
            flag = false;
            break;
        }
        now = tri[s[i]-'a'][now];
    }
    if(flag){
        for(int i = 1;i < n;i++)
            if(show[i][now])
                printf("%d ",i);
        if(show[n][now])
            printf("%d",n);
    }
    puts("");
}

int main(){
    n = read();
    for(int i = 1;i <= n;i++){
        int l = read();
        for(int j = 1;j <= l;j++)
            insert(i);
    }
    int m = read();
    for(int i = 1;i <= m;i++)
        check();
    return 0;
}

你可能感兴趣的:(洛谷题解,map,题解,trie树,模拟,洛谷,trie树,map)