1590: [Usaco2008 Dec]Secret Message 秘密信息
Time Limit: 5 Sec Memory Limit: 32 MB
Submit: 209 Solved: 143
[Submit][Status][Discuss]
Description
贝茜正在领导奶牛们逃跑.为了联络,奶牛们互相发送秘密信息.
信息是二进制的,共有M(1≤M≤50000)条.反间谍能力很强的约翰已经部分拦截了这些信息,知道了第i条二进制信息的前bi(l《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
INPUT DETAILS:
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.
Sample Output
1
3
1
1
2
HINT
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 matches
Source
题解:一道比较有趣的字典树(Trie树)题目,可以很好地进行前缀的比对,如果要是只是在前N个序列中找后M个的前缀个数的话那就是一道模板题。。。只是在这里显然还需要考虑在后M个里面找前N个的前缀,那么其实也就只需要在字典树里面多存储一种值即可,也就是子树的信息,具体有点讲不清,看程序吧,写的还算清晰。。。
(注意考虑匹配了一半的情况,那样子算是失败哦,为此我WA了一次)
1 type 2 point=^node; 3 node=record 4 tt,ex:longint; 5 next:array[0..1] of point; 6 end; 7 var 8 i,j,k,l,m,n:longint; 9 head:point; 10 s1:ansistring; 11 function newp:point; 12 var p:point; 13 begin 14 new(p);p^.tt:=0;p^.ex:=0; 15 p^.next[0]:=nil;p^.next[1]:=nil; 16 exit(p); 17 end; 18 procedure insert(s1:ansistring); 19 var i:longint;p:point; 20 begin 21 p:=head; 22 for i:=1 to length(s1) do 23 begin 24 if p^.next[ord(s1[i])-48]=nil then 25 p^.next[ord(s1[i])-48]:=newp; 26 p:=p^.next[ord(s1[i])-48]; 27 inc(p^.tt); 28 end; 29 inc(p^.ex); 30 end; 31 function num(s1:ansistring):longint; 32 var i,j,k,l:longint;p:point; 33 begin 34 p:=head;j:=0;k:=0;l:=0; 35 for i:=1 to length(s1) do 36 begin 37 if p^.next[ord(s1[i])-48]=nil then break; 38 p:=p^.next[ord(s1[i])-48]; 39 k:=k+j; 40 j:=p^.ex; 41 l:=i; 42 end; 43 if l<>i then num:=k+j else num:=k+p^.tt; 44 end; 45 begin 46 readln(n,m); 47 head:=newp; 48 for i:=1 to n do 49 begin 50 read(l);s1:=‘‘; 51 for j:=1 to l do 52 begin 53 read(k); 54 s1:=s1+chr(48+k); 55 end; 56 readln; 57 insert(s1); 58 end; 59 for i:=1 to m do 60 begin 61 read(l);s1:=‘‘; 62 for j:=1 to l do 63 begin 64 read(k); 65 s1:=s1+chr(48+k); 66 end; 67 readln; 68 writeln(num(s1)); 69 end; 70 readln; 71 end.