【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
1
3
1
1
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
#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;
}