(写的都是初中小朋友czl早就切过的题……)

http://www.cnblogs.com/Lyush/p/3281546.html

 

POJ-1509 Glass Beads

UVA - 719 Glass Beads

题意:一个字符串可以将第一个字符放到最后一位,然后问不断这样做可以得到的字典序最小的字符串

sam模板题,copy一遍建个sam,然后直接在sam中跑一遍就行了。

sam记录了字符串的所有后缀(也随便记录了字串),从root开始到每个接受态节点都是一个后缀(或多个),从root开始到每个节点都是一个子串(或多个)。由于copy一遍后把所有的情况的包括进去了,那么只要跑len(原长)遍就行了!

const
  maxn=30000;
var
  step,pre:array[0..maxn]of longint;
  son:array[0..maxn,0..25]of longint;
  tot,tail,t:longint;

procedure add(x:longint);
var
  i,j,k,np,p:longint;
begin
  p:=tail;
  inc(tot);
  np:=tot;
  step[np]:=step[tail]+1;
  while (p>=0) and (son[p,x]=-1) do begin
    son[p,x]:=np;
    p:=pre[p];
  end;
  tail:=np;
  if p<0 then pre[np]:=0
  else
    if step[son[p,x]]=step[p]+1 then
      pre[np]:=son[p,x]
    else begin
      j:=son[p,x];
      inc(tot);
      k:=tot;
      for i:=0 to 25 do son[k,i]:=son[j,i];
      step[k]:=step[p]+1;
      pre[k]:=pre[j];
      pre[j]:=k;
      pre[np]:=k;
      while (p>=0) and (son[p,x]=j) do begin
        son[p,x]:=k;
        p:=pre[p];
      end;
    end;
end;

procedure work;
var
  s:ansistring;
  len,i,j,k,p:longint;
begin
  readln(s);
  len:=length(s);
  s:=s+s;
  for i:=1 to len<<1 do
    add(ord(s[i])-97);
  p:=0;
  for i:=1 to len do
    for j:=0 to 25 do
      if son[p,j]>=0 then begin
        p:=son[p,j];
        break;
      end;
  writeln(step[p]-len+1);
end;

begin
  readln(t);
  while t>0 do begin
    dec(t);
    fillchar(pre,sizeof(pre),255);
    fillchar(son,sizeof(son),255);
    fillchar(step,sizeof(step),0);
    tot:=0;
    tail:=0;
    work;
  end
end.
View Code

相关文章:

  • 2022-02-12
  • 2021-09-09
  • 2022-02-16
  • 2021-05-26
  • 2021-06-10
  • 2022-12-23
  • 2022-02-24
  • 2021-09-16
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-03-08
  • 2022-12-23
  • 2021-04-20
  • 2021-12-28
相关资源
相似解决方案