Bzoj 1729 [Usaco2005 dec] Cow Patterns 牛的模式匹配

原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1729
http://poj.org/problem?id=3167
这题类似kmp,但匹配的时候不是直接的关键字匹配,而是排名的匹配,在kmp的基础上,每次比较相同或不同不是直接的关键字比较,而是用树状数组统计小于当前数和等于当前数的数量,如果对应相同,即排名相同。

const
  MX=25;
  MXN=100050;
var
  tr1,tr2:array[0..MX] of longint;
  a,b,p,match,rec:array[0..MXN] of longint;
  n,m,i,j,k,cnt,s:longint;
procedure change1(x,k:longint);
  begin
    while (x<=MX) do
      begin
        inc(tr1[x],k);
        x:=x + x and (-x);
      end;
  end;
procedure change2(x,k:longint);
  begin
    while (x<=MX) do
      begin
        inc(tr2[x],k);
        x:=x + x and (-x);
      end;
  end;
function query1(x:longint):longint;
  begin
    query1:=0;
    while (x>0) do
      begin
        inc(query1,tr1[x]);
        x:=x - x and (-x);
      end;
  end;
function query2(x:longint):longint;
  begin
    query2:=0;
    while (x>0) do
      begin
        inc(query2,tr2[x]);
        x:=x - x and (-x);
      end;
  end;
begin
  read(n,m,s);
  for i:=1 to n do read(a[i]);
  for i:=1 to m do read(b[i]);
  fillchar(tr1,sizeof(tr1),0);
  fillchar(tr2,sizeof(tr2),0);
  p[1]:=0;j:=0;
  for i:=2 to m do
    begin
      while (j>0)and((query1(b[j+1]-1)<>query2(b[i]-1))or(query1(b[j+1])<>query2(b[i]))) do
        begin
          for k:=p[j]+1 to j do change1(b[k],-1);
          for k:=i-j to i-p[j]-1 do change2(b[k],-1);
          j:=p[j];
        end;
      if (query1(b[j+1]-1)=query2(b[i]-1))and(query1(b[j+1])=query2(b[i])) then
        begin
          change1(b[j+1],1);
          change2(b[i],1);
          inc(j);
        end;
      p[i]:=j;
    end;
  fillchar(tr1,sizeof(tr1),0);
  fillchar(tr2,sizeof(tr2),0);
  match[1]:=0;j:=0;
  for i:=1 to n do
    begin
      while (j>0)and((query1(b[j+1]-1)<>query2(a[i]-1))or(query1(b[j+1])<>query2(a[i]))) do
        begin
          for k:=p[j]+1 to j do change1(b[k],-1);
          for k:=i-j to i-p[j]-1 do change2(a[k],-1);
          j:=p[j];
        end;
      if (query1(b[j+1]-1)=query2(a[i]-1))and(query1(b[j+1])=query2(a[i])) then
        begin
          change1(b[j+1],1);
          change2(a[i],1);
          inc(j);
        end;
      match[i]:=j;
      if (j=m) then
        begin
          inc(cnt);
          rec[cnt]:=i-m+1;
          for k:=p[j]+1 to j do change1(b[k],-1);
          for k:=i-j+1 to i-p[j] do change2(a[k],-1);
          j:=p[j];
        end;
    end;
  writeln(cnt);
  for i:=1 to cnt do
    writeln(rec[i]);
end.

你可能感兴趣的:(Bzoj,Poj,精妙,kmp)