poj3693

来源:互联网 发布:java反射调用方法参数 编辑:程序博客网 时间:2024/09/21 09:26

【题意】

给定一个字符串(长度不超过100000),要求输出重复次数最多的字典序最小的子串

【输入】

多组数据,每组数据一行,为一个小写字母组成的字符串

数据以#结束

【输出】

每组输出'Case *: '+重复次数最多字典序最小的子串


后缀数组求解

然后枚举重复部分的长度l

然后在l+1、2*l+1...位置枚举

若枚举到l+1若1和l+1上的字符相同,

则求1和l+1向前匹配的长度和向后匹配的长度。

然后将向前向后匹配长度相加再加上l然后div l

便是重复次数p

字典序的比较,比较一下起点的rank即可

需要注意的是向前匹配的最左端到最右端向前p*l都可以作为字符串的起点

用st算法可求出rank最小的起点


program poj3693;const  ln2=1/ln(2);type  arr=array [-1..100001] of longint;  arra=array [0..18,0..100001] of longint;var  n,i,j,k,l,max,where,t,s,e,mid,long,q,p,tot:longint;  ok:boolean;  root,nroot:ansistring;  nrank,nheight,sa,dl,height,total,rank,now,keep,change:arr;  min,dict,nmin:arra;procedure swap (var a,b:longint);var  i:longint;begin  i:=a;  a:=b;  b:=i;end;procedure solve (var rank,height:arr;root:ansistring);begin  fillchar(total,sizeof(total),0);  for i:=1 to n do    inc(total[ord(root[i])-96]);  for i:=1 to 26 do    total[i]:=total[i-1]+total[i];  for i:=1 to n do    rank[i]:=total[ord(root[i])-97]+1;  k:=0;  while 1 shl k<n do    begin      for i:=1 to n do        if i+(1 shl k)>n then change[i]:=0                         else change[i]:=rank[i+(1 shl k)];      fillchar(total,sizeof(total),0);      for i:=1 to n do        inc(total[change[i]]);      for i:=1 to n do        total[i]:=total[i]+total[i-1];      for i:=1 to n do        begin          dl[total[change[i]-1]+1]:=i;          inc(total[change[i]-1]);        end;      fillchar(total,sizeof(total),0);      ok:=true;      for i:=1 to n do        begin          inc(total[rank[i]]);          if total[rank[i]]=2 then ok:=false;        end;      if ok then break;      for i:=2 to n do        total[i]:=total[i]+total[i-1];      fillchar(now,sizeof(now),0);      fillchar(keep,sizeof(keep),0);      for i:=1 to n do        begin          if now[rank[dl[i]]]<>change[dl[i]] then            begin              now[rank[dl[i]]]:=change[dl[i]];              total[rank[dl[i]]-1]:=total[rank[dl[i]]-1]+keep[rank[dl[i]]];              keep[rank[dl[i]]]:=0;            end;          inc(keep[rank[dl[i]]]);          rank[dl[i]]:=total[rank[dl[i]]-1]+1;        end;      inc(k);    end;  for i:=1 to n do    sa[rank[i]]:=i;  fillchar(height,sizeof(height),0);  for i:=1 to n do    begin      if rank[i]=1 then continue;      k:=height[rank[i-1]]-1;      if k<0 then k:=0;      while (i+k<=n)and(sa[rank[i]-1]+k<=n)and(root[i+k]=root[sa[rank[i]-1]+k]) do inc(k);      height[rank[i]]:=k;    end;end;procedure st (var height:arr;var min:arra);begin  for i:=1 to n do    min[0,i]:=height[i];  k:=0;  while 1 shl k<n do    begin      for i:=1 to n do        if i+(1 shl k)>n then          min[k+1,i]:=min[k,i]                         else        if min[k,i]<min[k,i+(1 shl k)] then          min[k+1,i]:=min[k,i]                                       else          min[k+1,i]:=min[k,i+(1 shl k)];      inc(k);    end;end;procedure dictst;begin  for i:=1 to n do    dict[0,i]:=i;  k:=0;  while 1 shl k<n do    begin      for i:=1 to n do        if i+(1 shl k)>n then          dict[k+1,i]:=dict[k,i]                         else        if rank[dict[k,i]]<rank[dict[k,i+(1 shl k)]] then          dict[k+1,i]:=dict[k,i]                                                     else          dict[k+1,i]:=dict[k,i+(1 shl k)];      inc(k);    end;end;function similar (a,b:longint;var min:arra;var rank,height:arr):longint;var  i:longint;begin  if a=b then exit(n-a+1);  a:=rank[a];  b:=rank[b];  if a>b then swap(a,b);  inc(a);  if a=b then exit(height[a]);  i:=trunc(ln(b-a)*ln2);  while (i>0)and(1 shl i>=b-a+1) do dec(i);  if min[i,a]<min[i,b-(1 shl i)+1] then exit(min[i,a])                                   else exit(min[i,b-(1 shl i)+1]);end;function similardict (a,b:longint):longint;var  i:longint;begin  if a=b then exit(a);  i:=trunc(ln(b-a)*ln2);  while (i>0)and(1 shl i>=b-a+1) do dec(i);  if rank[dict[i,a]]<rank[dict[i,b-(1 shl i)+1]] then exit(dict[i,a])                                                 else exit(dict[i,b-(1 shl i)+1]);end;begin  t:=0;  repeat    readln(root);    if root='#' then break;    inc(t);    n:=length(root);    tot:=0;    solve(rank,height,root);    st(height,min);    nroot:=root;    for i:=1 to n do      nroot[i]:=root[n-i+1];    solve(nrank,nheight,nroot);    st(nheight,nmin);    dictst;    max:=1;    long:=1;    where:=1;    for i:=2 to n do      if root[i]<root[where] then where:=i;    for l:=1 to n div 2 do      if n div l >= max then        for i:=1 to n div l  do          if n div l - i + 3>=max then          begin            if i*l+1>n then continue;            if root[(i-1)*l+1]<>root[i*l+1] then continue;            s:=(i-1)*l+1-similar(n-(i-1)*l+1,n-i*l+1,nmin,nrank,nheight);            k:=similar(s,s+l,min,rank,height)+l;            q:=k div l;            if q>=max then              begin                p:=similardict(s,s+k-q*l);                if (q>max)or                ((q=max)and(rank[where]>rank[p])) then                  begin                    max:=q;                    where:=p;                    long:=l;                  end;              end;          end;    write('Case ',t,': ');    for i:=where to where+max*long-1 do      write(root[i]);    writeln;  until false;end.


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 客厅吊灯买大了怎么办 贝聊等登不上去怎么办 酒店订错了时间怎么办 辞职后奖金不发怎么办 小孩被水母蛰了怎么办 被剧毒水母蛰了怎么办 被水母蛰了很痒怎么办 ipo被否了将来怎么办 科技布沙发裂了怎么办 35岁皮肤皱纹多怎么办 22岁皮肤皱纹多怎么办 腿上皮肤皱纹多怎么办 16岁皮肤有皱纹怎么办 28岁皮肤有皱纹怎么办 眼睛上有血管翳怎么办 鸽子家飞时间短怎么办 宝宝吃母乳不吃奶瓶怎么办 邮件群发超50人怎么办 鸽子拉白色水便怎么办 进京没办进京证怎么办 吃海鲜喝牛奶了怎么办 煎牛排油少了怎么办 网上订酒店去后怎么办 澳洲语言班没过怎么办 照片粘在玻璃上怎么办 照片粘玻璃上怎么办啊 个人3月旅游签证怎么办 澳洲签证拒签了怎么办 我想买房子可是没钱怎么办 微信身份证17位怎么办 身份证后4位泄露怎么办 车牌照掉了一个怎么办 车牌螺丝孔坏了怎么办 借了贷款还不起怎么办 谷歌验证码丢了怎么办 谷歌验证码错误怎么办 未满16岁怎么办银行卡 身份证在北京丢了怎么办 出国前护照丢了怎么办 在美国护照丢了怎么办 护照上照片太丑怎么办