这道题还是很有意思的。题目大意如下:
给定一个模式串,如果在主串中存在这样一个子串:子串长度与模式串长度相同,且子串中各个数字的大、小、同关系和模式串中的大、小、同关系是一样的,就称该子串满足条件。
比如说模式串:1,4,4,2,3,1 而主串:5,6,2,10,10,7,3,2,9
那么主串第三位开始的2,10,10,7,3,2就是满足条件的
具体的算法很巧妙:我们对于每一个模式串中的数字要进行预处理,处理的方法很简单:分别找出三个数字作为它的定位数字:
1、前面离它最近的比它小的最大的数字的编号
2、前面离它最近但不是它本身的和它相同的数字的编号
3、前面离它最近的比它大的最小的数字的编号
有了这三个定位数字,就可以求出串中每个数字与它定位数字间的距离,如果距离相同,则匹配成功,否则跳到它的pre函数值上。
CODE
Program Cpattern;//By_thispoet
Const
maxn=100001;
Var
i,j,k,m,n,p,q,s :Longint;
st,a,rank,mins,mina,pre :Array[0..maxn]of Longint;
ja,js :Array[0..maxn,0..2]of Longint;
ans :Array[0..maxn]of Longint;
Function Funa(i,j:Longint):Boolean;
begin
Funa:=true;
Funa:=Funa and ((i-ja[i,0]=j-ja[j,0])or((ja[i,0]=ja[j,0])and(ja[i,0]=-1)));
Funa:=Funa and ((i-ja[i,1]=j-ja[j,1])or((ja[i,1]=ja[j,1])and(ja[i,1]=-1)));
Funa:=Funa and ((i-ja[i,2]=j-ja[j,2])or((ja[i,2]=ja[j,2])and(ja[j,2]=-1)));
end;
Function Funs(i,j:Longint):Boolean;
begin
Funs:=true;
Funs:=Funs and ((i-js[i,0]=j-ja[j,0])or((js[i,0]=ja[j,0])and(js[i,0]=-1)));
Funs:=Funs and ((i-js[i,1]=j-ja[j,1])or((js[i,1]=ja[j,1])and(js[i,1]=-1)));
Funs:=Funs and ((i-js[i,2]=j-ja[j,2])or((js[i,2]=ja[j,2])and(js[i,2]=-1)));
end;
Procedure Get_ja(p,q:Longint);
var k:Longint;
begin
fillchar(ja[p],sizeof(ja[p]),255);
k:=a[p];
for j:=k-1 downto 1 do
if mina[j]>=q then
begin
ja[p,0]:=mina[j];
break;
end;
for j:=k+1 to s do
if mina[j]>=q then
begin
ja[p,2]:=mina[j];
break;
end;
if (mina[k]>=q)and(mina[k]<p)then ja[p,1]:=mina[k];
end;
Procedure Kmp_Prepare;
begin
mina[a[1]]:=1;
pre[1]:=0;
Get_ja(1,0);
for i:=2 to m do
begin
k:=pre[i-1];
while (k<>0) do
begin
Get_ja(i,i-k);
if Funa(k+1,i) then
begin
pre[i]:=k+1;
break;
end;
k:=pre[k];
end;
if k=0 then pre[i]:=1;
Get_ja(i,0);
mina[a[i]]:=i;
end;
fillchar(mina,sizeof(mina),255);
end;
Procedure Get_js(p,q:Longint);
var j,k:Longint;
begin
fillchar(js[p],sizeof(js[p]),255);
k:=st[p];
for j:=k-1 downto 1 do
if mins[j]>=q then
begin
js[p,0]:=mins[j];
break;
end;
for j:=k+1 to s do
if mins[j]>=q then
begin
js[p,2]:=mins[j];
break;
end;
if (mins[k]>=q)and(mins[k]<p) then js[p,1]:=mins[k];
end;
Procedure Kmp;
var k:Longint;
begin
p:=1;q:=1;mins[st[1]]:=1;
while (p<n) do
begin
Get_js(p+1,p-q+1);
if Funs(p+1,q+1)then
begin
inc(p);inc(q);
end else
begin
q:=pre[q];
while q<>0 do
begin
Get_js(p+1,p-q+1);
if Funs(p+1,q+1) then
begin
inc(p);inc(q);
break;
end;
q:=pre[q];
end;
if q=0 then
begin
inc(p);inc(q);
end;
end;
mins[st[p]]:=p;
if q=m then
begin
inc(ans[0]);
ans[ans[0]]:=p-q+1;
q:=pre[q];
end;
end;
end;
BEGIN
readln(n,m,s);
for i:=1 to n do readln(st[i]);
for i:=1 to m do readln(a[i]);
fillchar(mina,sizeof(mina),255);
Kmp_Prepare;
fillchar(mins,sizeof(mins),255);
fillchar(js,sizeof(js),255);
ans[0]:=0;
Kmp;
writeln(ans[0]);
for i:=1 to ans[0] do writeln(ans[i]);
END.