[USACO 1.3.3] Calf Flac

[題目描述]

Calf Flac

據說如果你給無限只母牛和無限臺巨型便攜式電腦(有非常大的鍵盤),那麼母牛們會製造出世上最棒的迴文。你的工作就是去這些牛製造的奇觀(最棒的迴文)。在尋找回文時不用理睬那些標點符號、空格(但應該保留下來以便做爲答案輸出),只用考慮字母'A'-'Z'和'a'-'z'。要你尋找的最長的迴文的文章是一個不超過20,000個字符的字符串。我們將保證最長的迴文不會超過2,000個字符(在除去標點符號、空格之前)。

PROGRAM NAME: calfflac

INPUT FORMAT

一個不超過20,000個字符的文件。

SAMPLE INPUT (file calfflac.in)

Confucius say: Madam, I'm Adam.

OUTPUT FORMAT

輸出的第一行應該包括找到的最長的迴文的長度。
下一個行或幾行應該包括這個迴文的原文(沒有除去標點符號、空格),
把這個迴文輸出到一行或多行(如果迴文中包括換行符)。
如果有多個迴文長度都等於最大值,輸出那個前出現的。

SAMPLE OUTPUT (file calfflac.out)

11
Madam, I'm Adam


[解題思路]

很模型的【最長迴文串】,有點小噁心,主要是換行符不能忽略。

以前打的最長迴文串都是NlogN的字符串Hash,不過還有更優的Manacher算法,可以O(N)的出解。

Manacher算法相關,請移步這裏


[Code]

{
ID: zane2951
PROG: calfflac
LANG: PASCAL
}

program calfflac;
var
   p,r:array[0..211111] of longint;
   s,ss:ansistring;
   len,i,lim,now,ce,t,ans:longint;

//----------min------------
function min(a,b:longint):longint;
begin
   if a<b then exit(a) else exit(b);
end;

//----------main-----------
begin
   assign(input,'calfflac.in'); reset(input);
   assign(output,'calfflac.out'); rewrite(output);
   s:='';
   while not seekeof do
      begin
         readln(ss);
         if s<>'' then s:=s+'~'+ss else s:=ss;
      end;
   len:=length(s);
   ss:='#'; t:=1; p[1]:=1;
   for i:=1 to len do
      begin
         ce:=ord(s[i]);
         if (ce>=65) and (ce<=90) then
            begin ss:=ss+s[i]+'#'; inc(t); p[t]:=i; inc(t); p[t]:=i; end
               else if (ce>=97) and (ce<=122) then
                  begin ss:=ss+upcase(s[i])+'#'; inc(t); p[t]:=i;inc(t); p[t]:=i; end;
      end;
   lim:=0; now:=0;
   for i:=1 to t do
      begin
         if lim>i then r[i]:=min(r[now<<1-i],lim-i) else r[i]:=1;
         while (i-r[i]>0) and (i+r[i]<=t) do
            if (ss[i-r[i]]=ss[i+r[i]]) then inc(r[i]) else break;
         if r[i]+i>lim then
            begin
               lim:=r[i]+i;
               now:=i;
            end;
      end;
   ce:=-1;
   for i:=1 to t do if r[i]>ce then begin ce:=r[i]; ans:=i; end;
   dec(ce);
   writeln(ce);
   for i:=p[ans-ce+1] to p[ans+ce] do if s[i]='~' then writeln else write(s[i]);
   writeln;
   close(input); close(output);
end.
發佈了41 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章