bzoj 1398 &&bzoj 2882最小表示法

61 篇文章 0 订阅

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

直到i或j大于串长,找较小者 即 min(i,j)。

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

            [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 (i<l) and (j<l) do
   begin
      k:=0;
      while (s[i+k]=s[j+k]) and (k<l) do inc(k);
      if k=l then break;
      if s[i+k]>s[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 (i<n) and (j<n) do
   begin
      k:=0;
      while (a[i+k]=a[j+k]) and (k<n) do inc(k);
      if k=n then break;
      if a[i+k]>a[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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值