题目描述
英语老师留了 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
说明/提示
m<=10000,n<=1000.
每篇短文长度<=5000字符(含空格),每个单词长度≤20 字符。
每个测试点时限 2 秒。
思路
本人首先想到的本来是Hash,但因为本人太菜竟全WA了,所以我一气之下选用了似乎更容易上手的字典树.方法:将每排的单词全部存入字典树内并用一个数组如ju[p][i]标记第i行出现单词p。
然后在检索模式串,及查询trie树内是否存有该单词,若无直接返回;
若有就扫描并输出标记的值(注意不管有没有都得换行!)
代码
#include<bits/stdc++.h>
#define N 500005 //尽量开大
using namespace std;
int tree[N][26],n,m,cnt=0,k;
bool ju[N][1001];
char s[201];
void Build(char *s,int x,int len)//构建trie树
{
int p=0;
for(int i=1;i<=len;i++)
{
int c=s[i]-'a';
if(!tree[p][c])tree[p][c]=++cnt;
p=tree[p][c];
}
ju[p][x]=1;
return;
}
void Search(char *s,int len)//查询
{
int p=0;
for(int i=1;i<=len;i++)
{
int c=s[i]-'a';
if(!tree[p][c])return;
p=tree[p][c];
}
for(int i=1;i<=n;i++)
if(ju[p][i])printf("%d ",i);
return;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&m);
for(int j=1;j<=m;j++)
{
scanf("%s",s+1);
Build(s,i,strlen(s+1));
}
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%s",s+1);
Search(s,strlen(s+1));
cout<<endl;//不要忘了换行!
}
return 0;
}