zoukankan      html  css  js  c++  java
  • 【BZOJ1031】字符加密Cipher(后缀数组)

    题意:将一个长度为2n(复制粘贴后)的字符串的所有长度为n的后缀从小到大排序,并依次输出它们的最后一个字母。

    n<=100000

    思路:裸SA,模板真难背

    P党不得不写成C++风格

     1 var ch:array[0..300000]of char;
     2     a,x,y,wc,wd,sa:array[0..300000]of longint;
     3     n,i,m:longint;
     4     tmp:char;
     5  
     6 function cmp(a,b,l:longint):boolean;
     7 begin
     8  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
     9 end;
    10  
    11 procedure swap(var x,y:longint);
    12 var t:longint;
    13 begin
    14  t:=x; x:=y; y:=t;
    15 end;
    16  
    17 procedure getsa;
    18 var i,j,p:longint;
    19 begin
    20  for i:=0 to n-1 do
    21  begin
    22   x[i]:=a[i];
    23   inc(wc[a[i]]);
    24  end;
    25  for i:=1 to m do wc[i]:=wc[i-1]+wc[i];
    26  for i:=n-1 downto 0 do
    27  begin
    28   dec(wc[x[i]]);
    29   sa[wc[x[i]]]:=i;
    30  end;
    31  
    32  j:=1; p:=1;
    33  while p<n do
    34  begin
    35   p:=0;
    36   for i:=n-j to n-1 do
    37   begin
    38    y[p]:=i; inc(p);
    39   end;
    40   for i:=0 to n-1 do
    41    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
    42  // for i:=0 to n-1 do writeln(y[i]);
    43   for i:=0 to n-1 do wd[i]:=x[y[i]];
    44   for i:=0 to m do wc[i]:=0;
    45   for i:=0 to n-1 do inc(wc[wd[i]]);
    46   for i:=1 to m do wc[i]:=wc[i-1]+wc[i];
    47   for i:=n-1 downto 0 do
    48   begin
    49    dec(wc[wd[i]]);
    50    sa[wc[wd[i]]]:=y[i];
    51   end;
    52  
    53   for i:=0 to n do swap(x[i],y[i]);
    54  
    55   p:=1; x[sa[0]]:=0;
    56   for i:=1 to n-1 do
    57   begin
    58    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
    59     else begin x[sa[i]]:=p; inc(p); end;
    60   end;
    61  
    62   j:=j*2;
    63   m:=p;
    64  end;
    65 end;
    66  
    67  
    68 begin
    69   assign(input,'bzoj1031r.in'); reset(input);
    70   assign(output,'bzoj1031r.out'); rewrite(output);
    71  while not eoln do
    72  begin
    73   read(tmp);
    74   inc(n);
    75   ch[n]:=tmp;
    76  end;
    77  for i:=1 to n do a[i-1]:=ord(ch[i]);
    78  for i:=n to n*2-1 do a[i]:=a[i-n];
    79  n:=n*2+1; m:=300;
    80  getsa;
    81  for i:=1 to n-1 do
    82   if sa[i]<(n>>1) then
    83   begin
    84    if sa[i]=0 then write(chr(a[n-2]))
    85     else write(chr(a[sa[i]-1]));
    86   end;
    87  close(input);
    88 close(output);
    89  
    90  
    91 end.
  • 相关阅读:
    20201015-3 每周例行报告
    20201008-1 每周例行报告
    20200924-1 每周例行报告
    20200924-3 单元测试,结对
    刷题-Leetcode-120. 三角形最小路径和
    刷题-Leetcode-1025. 除数博弈
    刷题-Leetcode-217. 存在重复元素
    刷题-Leetcode-24.两两交换链表中的节点
    刷题-AcWing-104. 货仓选址
    ARP报文抓包解析实验报告
  • 原文地址:https://www.cnblogs.com/myx12345/p/6407261.html
Copyright © 2011-2022 走看看