poj1226,poj3080

时间:2023-03-08 22:26:27

看来以后用pascal的函数要小心了;

简简单单pos其实时间复杂度是二次方级的……

今天学习的是KMP——字符匹配算法;

这两道题也都很简单,都是为这个算法练手的,

最朴素的匹配显然是穷举起始位置然后看是否匹配,复杂度O(nm)不尽人意

kmp的思想就是尽可能利用之前匹配的信息进行匹配。

具体分析我就不讲了,传送门http://www.cppblog.com/oosky/archive/2006/07/06/9486.html讲的很详细

但据说这两题暴力都可过……

 var a:array[..] of string;
next:array[..] of integer;
f:array[..] of boolean;
s:string;
c:char;
i,j,l,t,p,v,n,w:integer;
procedure work_next(s:string);
var i:integer;
begin
fillchar(next,sizeof(next),);
i:=;
j:=;
next[]:=;
while i<=l do
begin
if (j=) or (s[i]=s[j]) then
begin
inc(i);
inc(j);
next[i]:=j;
end
else j:=next[j];
end;
end;
function compare(a,b:string):boolean;
var i,j,l1:integer;
begin
i:=;
j:=;
l1:=length(a);
while (i<=l1) and (j<=l) do
begin
if (j=) or (a[i]=b[j]) then
begin
inc(i);
inc(j);
end
else j:=next[j];
end;
if j>l then exit(true) else exit(false);
end; procedure kmp;
var j:integer;
begin
for j:= to n do
begin
if (j=v) or f[j] then continue;
if (compare(a[j],s)) then
begin
f[j]:=true;
w:=w+;
end;
end;
end; begin
readln(t);
for p:= to t do
begin
readln(n);
v:=;
for i:= to n do
begin
readln(a[i]);
if (v=) or (length(a[i])<length(a[v])) then v:=i;
end;
for l:=length(a[v]) downto do
begin
for i:= to length(a[v])-l+ do
begin
w:=;
fillchar(f,sizeof(f),false);
s:=copy(a[v],i,l);
work_next(s);
kmp;
for j:= to l div do
begin
c:=s[j];
s[j]:=s[l-j+];
s[l-j+]:=c;
end;
work_next(s);
kmp;
if w=n then break;
end;
if w=n then break;
end;
if w=n then writeln(l) else writeln();
end;
end.

poj1226