USACO Training Section 1.3 Calf Flac 解题报告&AC代码

博客详细介绍了如何使用生长法解决USACO训练题目Calf Flac,寻找字符串中最长的回文。在忽略特定字符后,确保回文不超过2,000字符。AC代码和输入输出格式也被提供。" 108945077,10130757,C++解决A×B问题,['C++'],"['C++', '算法', '数学运算', '编程', '乘法']
摘要由CSDN通过智能技术生成

解题报告:

主要方法是生长法,考虑每一位的左右各有多长的回文串,输出最长的那个,比较好想……不过要注意区分字串的奇偶。

其他实现细节看代码里的注释吧……

AC代码:

/*
ID: yuanmz91
PROG: calfflac
LANG: C++
*/
#include <fstream>
#include <cstdlib>
#include <memory.h>
using namespace std;
const int MAX_LEN = 20010;  //最长20000
int main()
{
    ifstream fin("calfflac.in");
    ofstream fout("calfflac.out");
    char original[MAX_LEN], words[MAX_LEN];  //原文和只含大写字母的字串
    int orglen = 0, wrdlen = 0, ltrloc[MAX_LEN];  //原文长度、处理后长度和处理后的串每个字符在原文中的位置
    memset(ltrloc, 0, sizeof(ltrloc));  //清空,其实可以不做
    while(fin.get(original[orglen]))  //一直读,注意要用get,把换行符什么的都要读进来
    {
        if(isalpha(original[orglen]))  //判断是否为字母
        {
            words[wrdlen] = toupper(original[orglen]);  //转换成大写存起来
            ltrloc[wrdlen] = orglen;  //记录这个字母在原串中的位置
            wrdlen++;  //标记右移
        }
        orglen++;  //标记右移
    }
    int maxlen = 0, start;  //最长回文串半长度和最长回文串中心位置
    for(int i = 0; i != wrdlen; ++i)  //遍历整个处理后的串
    {
        int len = 0;  //长度至少为0嘛
        while((words[i + len] == words[i - len]) && ((i - len) >= 0) && ((i + len) < wrdlen))  //我们要保证既不越界,又要回文,所以出现了这三个判断。分别是判回文、判越下界和判越上界
        {
            len++;  //如果都满足,长度加1
        }
        if(len > maxlen)  //如果这个长度是新纪录,那么存起来
        {
            maxlen = len;
            start = i;
        }
    }
    int dmaxlen = 0, dstart;  //这个是偶数位的处理,与奇数位大同小异
    for(int i = 0; i != wrdlen; ++i)
    {
        int dlen = 0;
        while((words[i + dlen + 1] == words[i - dlen]) && ((i - dlen) >= 0) && ((i + dlen + 1) < wrdlen))
        {
            dlen++;
        }
        if(dlen > dmaxlen)
        {
            dmaxlen = dlen;
            dstart = i;
        }
    }
    maxlen = maxlen * 2 - 1;
    dmaxlen *= 2;
    if(maxlen > dmaxlen)
    {
        fout << maxlen << endl;
        for(int i = ltrloc[start - (maxlen + 1) / 2 + 1]; i <= ltrloc[start + (maxlen + 1) / 2 - 1]; ++i)  //记录的位置在这里派上用场了
        {
            fout << original[i];
        }
    }
    else
    {
        fout << dmaxlen << endl;
        for(int i = ltrloc[dstart - (dmaxlen / 2) + 1]; i <= ltrloc[dstart + (dmaxlen / 2)]; ++i)
        {
            fout << original[i];
        }
    }
    fout << endl;
    return 0;
}

下面是题:

英文版

Calf Flac

It is said that if you give an infinite number of cows an infinite number of heavy-duty laptops (with very large keys), that they will ultimately produce all the world's great palindromes. Your job will be to detect these bovine beauties.

Ignore punctuation, whitespace, numbers, and case when testing for palindromes, but keep these extra characters around so that you can print them out as the answer; just consider the letters `A-Z' and `a-z'.

Find the largest palindrome in a string no more than 20,000 characters long. The largest palindrome is guaranteed to be at most 2,000 characters long before whitespace and punctuation are removed.

PROGRAM NAME: calfflac

INPUT FORMAT

A file with no more than 20,000 characters. The file has one or more lines which, when taken together, represent one long string. No line is longer than 80 characters (not counting the newline at the end).

SAMPLE INPUT (file calfflac.in)

Confucius say: Madam, I'm Adam.

OUTPUT FORMAT

The first line of the output should be the length of the longest palindrome found. The next line or lines should be the actual text of the palindrome (without any surrounding white space or punctuation but with all other characters) printed on a line (or more than one line if newlines are included in the palindromic text). If there are multiple palindromes of longest length, output the one that appears first.

SAMPLE OUTPUT (file calfflac.out)

11
Madam, I'm Adam
中文版

描述

据说如果你给无限只母牛和无限台巨型便携式电脑(有非常大的键盘),那么母牛们会制造出世上最棒的回文。你的工作就是去寻找这些牛制造的奇观(最棒的回文)。

在寻找回文时不用理睬那些标点符号、空格(但应该保留下来以便做为答案输出),只用考虑字母'A'-'Z'和'a'-'z'。要你寻找的最长的回文的文章是一个不超过20,000个字符的字符串。我们将保证最长的回文不会超过2,000个字符(在除去标点符号、空格之前)。  

 

格式

PROGRAM NAME: calfflac

INPUT FORMAT: (file calfflac.in)

输入文件不会超过20,000字符。这个文件可能一行或多行,但是每行都不超过80个字符(不包括最后的换行符)。

OUTPUT FORMAT: (file calfflac.out)

输出的第一行应该包括找到的最长的回文的长度。

下一行或几行应该包括这个回文的原文(没有除去标点符号、空格),把这个回文输出到一行或多行(如果回文中包括换行符)。

如果有多个回文长度都等于最大值,输出最前面出现的那一个。 

SAMPLE INPUT

Confucius say: Madam, I'm Adam.

SAMPLE OUTPUT

11
Madam, I'm Adam

下面是测试数据……吐槽一下……他丫的居然直接拿代码当测试数据……

Here are the test data inputs:

------- test 1 ----
Confucius say: Madam, I'm Adam.

------- test 2 ----
LupgTU{YtMzkojlNfWiuRXReZYzcoOwuGuqo{WEzQZe[LqoHxgNsDdoixRIReZplGXKgcSJthF[gcWkC

WinQvfIIgcikm[lk[kFB

------- test 3 ----
/*
ID: jweisbl1
LANG: JAVA
PROG: calfflac
*/
import java.io.*;
import java.util.*;
public class calfflac
{
    private int money=0;
    private String name="";
    public static void main(String[] args) throws Exception
    {
        FileOutputStream out; // declare a file output object 
                    PrintStream p; // declare a print stream object 
                        out = new FileOutputStream("calfflac.out"); // Connect print stream to the output stream
                        p = new PrintStream( out );
        Scanner in=new Scanner(new BufferedReader(new FileReader("calfflac.in")));
        StringBuffer str=new StringBuffer(in.nextLine());
        while(in.hasNextLine())
            str.append("\n"+in.nextLine());
            String maxPal="";
/
char[] letters=new char[str.length()];
int size=0,indices[]=new int[str.length()];
for(int i=0;i<str.length();i++)
{
    if(Character.isLetter(str.charAt(i)))
    {
        indices[size]=i;
        letters[size]=Character.toUpperCase(str.charAt(i));
        size++;
    }
}
int maxLength=0,maxCenter=0,maxAdd=0,maxDiff=0;
for(int center=Math.min(size-1,1);center<size;center++)
{
    for(int add=0;add<2;add++)
    {
        
        int diff=0;
        while(center-diff>=0 && center+diff+add<size)
        {
            if(letters[center+diff+add]==letters[center-diff])
            {
                diff++;
            }
            else
            {
                break;
            }
            
        }
        diff--;
        if(2*diff+add+1>maxLength)
        {
            maxLength=2*diff+add+1; maxCenter=center;maxDiff=diff;maxAdd=add;
            if(indices[center+diff+add]==str.length()-1)  maxPal=str.substring(indices[center-diff]);
            else maxPal=str.substring(indices[center-diff],indices[center+diff+add]+1);
        }//if
    }//even/odd
} //center
//for(int g=0;g<size;g++) System.out.print(g%10);
//System.out.println();
//for(int g=0;g<size;g++) System.out.print(letters[g]);
//System.out.println();
//System.out.println(maxPal+"\nlength="+maxLength+"\ncenter="+maxCenter+"\ndiff="+maxDiff+"\nadd="+maxAdd);
p.println(maxLength+"\n"+maxPal);        
p.close();
}//method
}//class
/*
private static in
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值