题目链接: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<iostream>
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
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<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
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;
}