Description
Input
第一行两个数n,m,表示有n个字符串,m个询问。
接下来n行,每行一个字符串Ti 。
再接下来m行,每行一个字符串Si 。
Output
对于每个询问,输出一个ansi表示答案。
Sample Input
3 2
abcabc
aabc
abbc
aa
ba
Sample Output
1
3
题解:看到前缀和只有abc,想到字典树
先对原始的字符串建立Trie,对Trie上每一个点建立形如(1,0,0,1)的数组,记录第i个原始串是否能匹配。在匹配模式串的时候就可以很容易得到答案。但是这么做会炸内存。
进一步思考可以发现,对于每个点上类似于(1,0,0,1,0,1)的数组,相邻的两个1对后续没有影响。因此在建树时,我们用一个ans数组记录 以第i个点为结尾的模式串 的答案。对于ans[i],当有模式串匹配到i点时,ans[i]=max(ans[i],time-last[i]-1) ,time指当前原始串的序号,last[i]指上一个匹配到该位置的原始串序号,即(1,0,0,1,0,1)中两个1的间隔。
注意:每个字符串的最后一个位置一直到n也是一个合法区间,不能遗漏,最终输出时比较max(ans[x],n-last[x])
const
maxn=100000;
maxm=5000000;
inf='word.in';
ouf='word.out';
var
ans,last:array[0..maxm]of longint;
trie:array[0..maxm,'a'..'c']of longint;
st:array[0..maxm]of char;
n,m,sum,len,i,j,flag:longint;
s:ansistring;
{procedure add(x,y:longint);
begin
inc(e[0]);
e[e[0]]:=y;
next[e[0]]:=last[x];
last[x]:=e[0];
end; }
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure build(st:ansistring;time:longint);
var
i,head,tail,flag,x:longint;
ch:char;
begin
x:=0;
for i:=1 to len do
begin
if trie[x,st[i]]=0 then
begin
inc(sum);
trie[x,st[i]]:=sum;
x:=sum;
ans[x]:=max(ans[x],time-last[x]-1);
last[x]:=time;
continue;
end;
x:=trie[x,st[i]];
ans[x]:=max(time-last[x]-1,ans[x]);
last[x]:=time;
end;
end;
procedure init;
var
i,j,sum:longint;
s:ansistring;
begin
readln(n,m);
for i:=1 to n do
begin
readln(s);
len:=length(s);
build(s,i);
end;
end;
function find(st:ansistring):longint;
var
x,i:longint;
begin
x:=0;
for i:=1 to len do
begin
if trie[x,st[i]]=0 then exit(n);
x:=trie[x,st[i]];
end;
exit(max(ans[x],n-last[x]));
end;
begin
assign(input,inf);reset(input);
assign(output,ouf);rewrite(output);
init;
for i:=1 to m do
begin
readln(s);
len:=length(s);
writeln(find(s));
end;
close(input);close(output);
end.