字典树 [TJOI2010]阅读理解(洛谷 P3879)

[TJOI2010]阅读理解

题目描述

英语老师留了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

解法一:
STL+思维;

这里用到了map > ma,比一般的map多了一个存储功能;非常好用;

调用vector里面的数要用ma[i].size();

代码:

#include
#define LL long long
#define pa pair
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=500100;
const int M=50100;
const LL mod=1e9+7;
map<string,vector<int> >ma;
int main(){
	ios::sync_with_stdio(false);
	int n,l;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>l;
		for(int j=1;j<=l;j++){
			string s;
			cin>>s;
			ma[s].push_back(i);
		}
	}
	int m;
	cin>>m;
	for(int i=1;i<=m;i++){
		string s;
		cin>>s;
		if(ma[s].empty()) cout<<endl;
		else{
			cout<<ma[s][0]<<" ";
			for(int j=1;j<ma[s].size();j++){
				if(ma[s][j]!=ma[s][j-1]) cout<<ma[s][j]<<" ";
			}
			cout<<endl;
		}
	}
	return 0;
}

解法二:

字典树

这道题的空间消耗有点大,如果记录数组用bool型都会MLE,改成bitset就行;

这道题跟模板题的区别,就是哪个记录数组用的非常巧妙,val[x][p],x代表第树的第几层,也表示那个单词,p代表第几行,然后赋值为1,表示这个单词在第几行出现过;

代码:

#include
#define LL long long
#define pa pair
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=500100;
const int M=50100;
const LL mod=1e9+7;
int tr[N][30];
bitset<1005>val[N];
int rt;
int n,l,m;
void add(string s,int p){
	int k=0;
	for(int i=0;i<s.length();i++){
		int d=s[i]-'a';
		if(!tr[k][d]) tr[k][d]=++rt;
		k=tr[k][d];
	}
	val[k][p]=1;
}
void search(string s){
	int k=0;
	int flag=1;
	for(int i=0;i<s.length();i++){
		int d=s[i]-'a';
		if(!tr[k][d]){
			flag=0;
			break;
		}
		k=tr[k][d];
	}
	if(flag){
		for(int i=1;i<=n;i++){
			if(val[k][i]==1) cout<<i<<" ";
		}
	}
	cout<<endl;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>l;
		for(int j=1;j<=l;j++){
			string s;
			cin>>s;
			add(s,i);
		}
	}
	cin>>m;
	for(int i=1;i<=m;i++){
		string s;
		cin>>s;
		search(s);
	}
	return 0;
}

你可能感兴趣的:(#,(01)字典树,字典树)