hdu 1358 Period KMP算法

题目:前缀子串能否有某个周期串重复k次,输出子串长度和最大的k,也就是最小周期情况下的k。也就是说求前缀子串的最大循环节。

分析:先把原字符串的next函数求出来,然后对每一个前缀进行枚举。假设现在枚举到第i个字符,若前i个前缀有循环节,则一定满足i mod (i-next[i])=0且i-next[i]为最大循环节的长度,因为是要找最小的循环节,所以就在最大的循环节的基础上继续找循环节,也就是找最大的循环节的循环节(仿佛一点都不饶),如此类推,直到找到最小的循环节为止就好了。

代码:

var
  len,i,j,tot,ans:longint;
  s:ansistring;
  next:array[0..1000000] of longint;

procedure get;
var
  i,j:longint;
begin
  next[0]:=-1;
  next[1]:=0;
  i:=2;
  j:=0;
  while i<=len do
    if (j=-1)or(s[j+1]=s[i])
      then begin
             inc(j);
             next[i]:=j;
             inc(i);
           end
      else j:=next[j];
end;

begin
  readln(len);
  while len>0 do
  begin
    inc(tot);
    writeln('Test case #',tot);
    readln(s);
    get;
    for i:=2 to len do
    begin
      j:=i;
      ans:=0;
      while (next[j]>0)and(i mod (i-next[j])=0) do
      begin
        ans:=i div (i-next[j]);
        j:=j-next[j];
      end;
      if ans>0 then writeln(i,' ',ans);
    end;
    readln(len);
    writeln; 
  end;
end.


你可能感兴趣的:(hdu 1358 Period KMP算法)