踹shu_Trie樹

【USACO Dec08】密信

Description

貝茜正在領導奶牛們逃跑.爲了聯絡,奶牛們互相發送祕密信息. 
信息是二進制的,共有M(1≤M≤50000)條.反間諜能力很強的約翰已經部分攔截了這些信息,知道了第i條二進制信息的前bi(1<bi≤10000)位.他同時知道,奶牛使用N(1≤N≤50000)條密碼.但是,他僅僅瞭解第J條密碼的前cj(1≤cj≤10000)位. 
對於每條密碼J,他想知道有多少截得的信息能夠和它匹配.也就是說,有多少信息和這條密碼有着相同的前綴.當然,這個前綴長度必須等於密碼和那條信息長度的較小者. 
在輸入文件中,位的總數(即∑Bi+∑Ci)不會超過500000.

Input

第1行輸入N和M,之後N行描述祕密信息,之後M行描述密碼.每行先輸入一個整數表示信息或密碼的長度,之後輸入這個信息或密碼.所有數字之間都用空格隔開.

Output

共M行,輸出每條密碼的匹配信息數.

Sample Input

4 5 
3 0 1 0 
1 1 
3 1 0 0 
3 1 1 0 
1 0 
1 1 
2 0 1 
5 0 1 0 0 1 
2 1 1

Sample Output





2

Hint

輸入解析: 
Four messages; five codewords. 
The intercepted messages start with 010, 1, 100, and 110. 
The possible codewords start with 0, 1, 01, 01001, and 11.

輸出解釋: 
0 matches only 010: 1 match 
1 matches 1, 100, and 110: 3 matches 
01 matches only 010: 1 match 
01001 matches 010: 1 match 
11 matches 1 and 110: 2 

















cnt記錄有多少個單詞以此爲前綴,stop記錄有多少個單詞以此結尾,另外,因爲同學的代碼比我的快,於是寫了讀入優化來優化常數

附上AC代碼,主要爲自己以後複習,也供參看
#include <cstdio>
#include <cstring>
const int MAXN=500001;
struct node {
	int stop,cnt,next[2];
} T[MAXN];
int n,m,tot;
 
inline int read(){
	char x=getchar();int ans=0;
	while(x<'0'||x>'9')x=getchar();
	while(x>='0'&&x<='9')ans=ans*10+x-'0',x=getchar();
	return ans;
}
 
inline void add(int len) {
	int p=0;
	for(int i=1,x; i<=len; i++) {
		x=read();
		if(T[p].next[x]==0)T[p].next[x]=++tot;
		p=T[p].next[x];
		T[p].cnt++;
	}
	T[p].stop++;
}
 
inline int query(int len) {
	int ans=0,p=0;
	for(int i=1,x; i<=len; i++) {
		x=read();
		if(!T[p].next[x]) {
			for(i++; i<=len; i++)x=read();
			return ans;
		}
		p=T[p].next[x];
		ans+=T[p].stop;
	}
	return ans-T[p].stop+T[p].cnt;
}
 
int main() {
	n=read(),m=read();
	for(int i=1; i<=n; i++)add(read());
	for(int i=1; i<=m; i++)printf("%d\n",query(read()));
	return 0;
}









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章