[题目描述]
Bessie the cow has a new cell phone and enjoys sending text messages,although she keeps making spelling errors since she has trouble typing onsuch a small screen with her large hooves. Farmer John has agreed to helpher by writing an auto-completion app that takes a partial word and suggests how to complete it.
The auto-completion app has access to a dictionary of W words, each consisting of lowercase letters in the range a..z, where the total number of letters among all words is at most 1,000,000. The app is given as input a list of N partial words (1 <= N <= 1000), each containing at most 1000 lowercase letters. Along with each partial word i, an integer K_i is also provided, such that the app must find the (K_i)th word in alphabetical order that has partial word i as a prefix. That is, if one ordered all of the valid completions of the ith partial word, the app should output the completion that is (K_i)th in this sequence.
为什么我要放英文的题面呢。。因为中文题面翻译的不好。。很多条件没加进去。。
这道题就是给定一个字符串,求整个字典中以这个为前缀的所有字符串中第k大。。
既然是前缀,看到的第一眼就想到了trie..
最开始的想法是先把他们读进来,然后排个序,离散化一下,然后建trie树
读入一个前缀后,把这个前缀在trie上跑过之后,跑完之后会停在一个节点上。。
然后就找这个节点的所有有end标记儿子的对应的离散化之后的值找第k小,然后输出相应的编号。。
想了想觉得空间会爆炸。。
然后想到一个新的方法。。
边读边建trie树,在建树的时候顺便记录一下经过这个节点的字符串数
读入一个前缀后,把这个前缀在trie上跑过之后,跑完之后会停在一个节点上。。
那么先找它下面的a
如果经过a的小于k,那么接着找b,不断递归下去。。
const shuru='auto.in';
shuchu='auto.out';
maxlen=1000;
type point=^node;
node=record
endless,data:longint;
next:array['a'..'z'] of point;
end;
str=array[0..maxlen] of char;
var start,p,q:point;
s:str;
len,i,j,k,n,m:longint;
ch:char;
procedure neww(var p:point);
begin
new(p);
p^.data:=0;
p^.endless:=0;
for ch:='a' to 'z' do p^.next[ch]:=nil;
end;
procedure forever(s:str;len,sign:longint);
var i:longint;
begin
p:=start;
for i:=1 to len do
begin
if p^.next[s[i]]=nil then begin
neww(p^.next[s[i]]);
p:=p^.next[s[i]];
end
else p:=p^.next[s[i]];
inc(p^.data);
end;
p^.endless:=sign;
end;
function ever(s:str;len,k:longint):longint;
var i:longint;
begin
p:=start;
for i:=1 to len do
begin
if p^.next[s[i]]=nil then exit(-1);
p:=p^.next[s[i]];
if p^.data<k then exit(-1);
end;
while not((k=1) and (p^.endless<>0)) do
begin
if p^.endless<>0 then dec(k);
for ch:='a' to 'z' do
if p^.next[ch]<>nil then if p^.next[ch]^.data>=k then begin
p:=p^.next[ch];
break;
end
else k:=k-p^.next[ch]^.data;
end;
exit(p^.endless);
end;
procedure init;
begin
neww(start);
readln(n,m);
for i:=1 to n do
begin
len:=0;
while not(eoln) do
begin
inc(len);
read(s[len]);
end;
readln;
forever(s,len,i);
end;
end;
procedure main;
begin
init;
for i:=1 to m do
begin
len:=0;
read(k);
read(s[1]);
while not(eoln) do
begin
inc(len);
read(s[len]);
end;
writeln(ever(s,len,k));
end;
end;
begin
main;
end.
extra: