这道题是一道kmp的扩展版的好题
一串匹配一串很容易想到kmp,但是这里的匹配要求的是两个串的名次相同
显然名次是会变的,为了方便,我们可以换一种表达
对于两个等长的串的相同位置,名次相等就是在它之前比它小的数的个数一样,和它相等的数的个数一样
这个我们可以用树状数组维护一下(当然暴力好像也行)
然后匹配就行了
1 var ans,a,b,sal,eq:array[0..100010] of longint; 2 next:array[0..30010] of longint; 3 c:array[0..30] of longint; 4 tot,k,n,m,s,i,j:longint; 5 6 function lowbit(x:longint):longint; 7 begin 8 exit(x and (-x)); 9 end; 10 11 procedure work(x,p:longint); 12 begin 13 while x<=s do 14 begin 15 inc(c[x],p); 16 x:=x+lowbit(x); 17 end; 18 end; 19 20 function ask(x:longint):longint; 21 begin 22 ask:=0; 23 while x>0 do 24 begin 25 ask:=ask+c[x]; 26 x:=x-lowbit(x); 27 end; 28 end; 29 30 begin 31 readln(n,m,s); 32 for i:=1 to n do 33 readln(a[i]); 34 for i:=1 to m do //预处理 35 begin 36 readln(b[i]); 37 work(b[i],1); 38 sal[i]:=ask(b[i]-1); 39 eq[i]:=ask(b[i]); 40 end; 41 fillchar(c,sizeof(c),0); 42 i:=1; 43 j:=0; 44 next[1]:=0; 45 while i<=m do 46 begin 47 if (j=0) or (ask(b[i]-1)=sal[j]) and (ask(b[i])=eq[j]) then 48 begin 49 inc(i); 50 inc(j); 51 next[i]:=j; 52 if i>m then break; 53 work(b[i],1); 54 end 55 else begin 56 for k:=i-j+1 to i-next[j] do // 保证匹配的串位置一样 57 work(b[k],-1); 58 j:=next[j]; 59 end; 60 end; 61 fillchar(c,sizeof(c),0); 62 i:=1; 63 j:=1; 64 work(a[1],1); 65 while (i<=n) do 66 begin 67 if (j=0) or (ask(a[i]-1)=sal[j]) and (ask(a[i])=eq[j]) then 68 begin 69 inc(i); 70 inc(j); 71 if i<=n then 72 work(a[i],1); 73 end 74 else begin 75 for k:=i-j+1 to i-next[j] do 76 work(a[k],-1); 77 j:=next[j]; 78 end; 79 if j>m then //注意这里要找出的是所有答案 80 begin 81 for k:=i-m to i-next[j] do 82 work(a[k],-1); 83 inc(tot); 84 ans[tot]:=i-m; 85 j:=next[j]; 86 end; 87 end; 88 writeln(tot); 89 for i:=1 to tot do 90 writeln(ans[i]); 91 end.