天天看點

P3879 [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
      

說明

對于30%的資料,1 ≤ M ≤ 1,000

對于100%的資料,1 ≤ M ≤ 10,000,1 ≤ N ≤ 1000

每篇短文長度(含相鄰單詞之間的空格) ≤ 5,000 字元,每個單詞長度 ≤ 20 字元

每個測試點時限2秒

這個題也是一個字典樹的題目,但是這個題目好像是沒有卡STL的,是以用STL也能過。

這個題用字典樹寫的話 數組開小了會WA#11,數組開大了前面就會有幾組資料MLE

通過了解 用 bitset 可以節省空間,把bool型的數改成 bitset就可以過了

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int t,n,m,tree[maxn][30],cnt;
bitset<1001> vis[maxn];
string x;
void insert(string s,int rt,int y)//一個個單詞的插入 y表示在第幾行句子中 
{
	int q=s.length();
	for(int i=0; i<q; i++)
	{
		int x=s[i]-'a';
		if(tree[rt][x]==0) tree[rt][x]=++cnt;
		rt=tree[rt][x];
	}
	vis[rt][y]=1;//标記 
}
void find(string s,int rt)
{
	int q=s.length();
	for(int i=0; i<q; i++)
	{
		int x=s[i]-'a';
		if(tree[rt][x]==0)
		{
			cout<<" "<<endl;//不存在則輸出空行 
			return ;
		}
		rt=tree[rt][x];
	}
	int flag=0;
	for(int i=1; i<=t; i++)//輸出 
	{
		if(flag==0&&vis[rt][i]==1)
		{
			flag=1;
			cout<<i;
		}
		else if(vis[rt][i]==1)
		{
			cout<<" "<<i;
		}
	}
	cout<<endl;
	return;
}
int main()
{
	cin>>t;
	for(int i=1; i<=t; i++)
	{
		cin>>n;
		while(n--)
		{
			cin>>x;
			insert(x,0,i);
		}
	}
	cin>>m;
	while(m--)
	{
		cin>>x;
		find(x,0);
	}
	return 0;
}