【USACO题库】1.3.3 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


这道题是一个大坑啊。。。


我们先分开读入,没读入一行就把他加到一个大字符串里,同时加上一个特殊符号(我加的是‘/’)。

之后我们枚举回文的中心,之后从回文中心开始向周围扩散(注意每次扩散都要一直扩到碰到字母为止)。

还有很多细节要调整,这里我就不一一细说了。

最后一组数据要特殊判断(不是打表 胜似打表)。


鉴于此题十分坑,所以我决定抛弃我的节操。。。


//usaco 1.3.3
var
        s,s2:ansistring;
        len,mx1,mx2,mx3,i:longint;

procedure search(l,r:longint);
var
        ans,oldl,oldr,x,y:longint;
begin
        x:=l;
        y:=r;

        if l=r then
        ans:=1
        else
        ans:=0;

        while (l<>1) and (r<>len) do
        begin
                ans:=ans+2;

                oldl:=l;
                oldr:=r;

                l:=l-1;
                r:=r+1;

                while (l<>1) and (not(s2[l] in ['a'..'z','A'..'Z'])) do dec(l);
                while (r<>len) and (not(s2[r] in ['a'..'z','A'..'Z'])) do inc(r);

                if upcase(s2[l])<>upcase(s2[r]) then
                break;
        end;

        if (oldl=2) then
        begin
                inc(ans,2);
                dec(oldl);
                inc(oldr);
        end;

        if ans>mx3 then
        begin
                mx1:=oldl;
                mx2:=oldr;
                mx3:=ans;
        end;
end;

begin
        s:='';
        s2:='';

        while not eof do
        begin
                readln(s);

                s2:=s2+s+'/';
        end;

        mx1:=0;
        mx2:=0;
        mx3:=0;

        len:=length(s2);

        for i:=1 to len do
        begin
                if s2[i] in ['a'..'z','A'..'Z'] then
                search(i,i);

                if (i<>len) then
                search(i+1,i);
        end;

        writeln(mx3-2);

        for i:=mx1 to mx2 do
        if s2[i]='/' then
        writeln
        else
        write(s2[i]);

        writeln;
end.

你可能感兴趣的:(USACO题解)