bzoj 1398 &&bzoj 2882最小表示法

bzoj 1398

题意:给出两个字符串,判断这两个串是否循环同构,如果循环同构同时输出字典序最小的表示

最小表示法模板题...

我们可以通过最小表示法做到O(len)

维护两个指针i、j,初始i=0 ,j=1,分别作为起点往下找到第一个不相等的字符 即s[i+k]<>s[j+k]

1、如果 k=len,就找到较小的 即 min(i,j)

1、  s[i+k]>s[j+k],j不变,i=i+k+1(优化:如果i+k+1<=j ,则i=j+1),然后继续往下比较。

2、  s[i+k]
直到i或j大于串长,找较小者 即 min(i,j)。

注意:[1]边界:保证i、j、k 均

            [2]由于比较的时候会超过原串的长度,有两种解决方式:①判断的时候取模 ②在处理之前把字符串复制一遍(但len依旧是原串的长度)

            [3]注意数据范围

吐槽:mdzz,这道题写得自己心态崩溃,果然蒟蒻还是回家种地比较好.....

uses math;
var
        l,t1,t2         :longint;
        i               :longint;
        ss,s1,s2        :ansistring;
        s               :array[0..2000010] of char;

function min_p(ss:ansistring):longint;
var
        i,j,k:longint;
begin
   for i:=0 to 2*l-1 do s[i]:=ss[i+1];
   i:=0; j:=1;
   while (is[j+k] then
      begin
         if i+k+1>j then i:=i+k+1 else i:=j+1;
      end else
      begin
         if j+k+1>i then j:=j+k+1 else j:=i+1;
      end;
   end;
   exit(min(i,j));
end;

begin
   readln(ss); l:=length(ss);
   ss:=ss+ss;
   t1:=min_p(ss);
   s1:=copy(ss,t1+1,l);
   //
   readln(ss); l:=length(ss);
   ss:=ss+ss;
   t2:=min_p(ss);
   s2:=copy(ss,t2+1,l);
   //
   if s1=s2 then
   begin
      writeln('Yes');
      writeln(s1);
   end else writeln('No');
end.

bzoj 2882

题意:求最小表示法

只能把最左边放到最右边和直接复制一遍放后面找循环同构有个毛区别....

uses math;
var
        n,t1            :longint;
        i               :longint;
        a               :array[0..600010] of longint;

function min_p:longint;
var
        i,j,k:longint;
begin
   i:=0; j:=1;
   while (ia[j+k] then
      begin
         if i+k+1>j then i:=i+k+1 else i:=j+1;
      end else
      begin
         if j+k+1>i then j:=j+k+1 else j:=i+1;
      end;
   end;
   exit(min(i,j));
end;

begin
   read(n);
   for i:=0 to n-1 do read(a[i]);
   for i:=0 to n-1 do a[n+i]:=a[i];
   t1:=min_p;
   for i:=t1 to t1+n-2 do write(a[i],' ');writeln(a[i+1]);
end.




——by Eirlys

bzoj 1398 &&bzoj 2882最小表示法_第1张图片


你可能感兴趣的:(bzoj,bzoj,模板)