【USACO1.3.3】回文串

来源:互联网 发布:三维设计软件 编辑:程序博客网 时间:2024/06/06 18:41

题目

【问题描述】

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

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

 我们将保证最长的回文不会超过2,000个字符(在除去标点符号、空格之前)。

【输入格式】  

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

【输出格式】  

输出的第一行应该包括找到的最长的回文的长度。
下一行或几行应该包括这个回文的原文(没有除去标点符号、空格),把这个回文输出到一行或多行(如果回文中包括换行符)。
如果有多个回文长度都等于最大值,输出最前面出现的那一个。

【输入样例】  

Confucius say: Madam, I’m Adam.

【输出样例】  

11
Madam, I’m Adam

分析

我们来想想回文串的判断方法,要么是直接判断,要么是dp,dp的话每种情况都会考虑到咋一想挺好的还特别好写,但是一算时间复杂度n*n是过不了的,而且剪枝很麻烦哎基本上剪不了
那我们就直接判断,这种方法时间复杂度也是n*n,但实际上中图有很多直接退出了,如果加上一个预测剪枝那绝对就是过了(我没加哈哈哈)
对于这种数据繁杂的题目,应该想到的是标准化,再想办法还原
还有一个就是答案的记录问题,之前有想过记录中间数,记录长度,直接记录数据什么的,但实际上只记录左端点是第几个字母+长度即可

代码

#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define LOCALconst int maxn=20005; char s[maxn],a[maxn];int n,m,chang,f;void Init(){    char c;    while( ( c = getchar() ) != EOF )    {        s[n++]=c;        c=tolower(c);        if(isalpha(c))            a[m++]=c;    }    s[n]='\0';    a[m]='\0';}void solve(){    for(int i=0;i<m;i++)//奇数     {        int l,r;        for(l=i,r=i;l>=0&&r<m;l--,r++)        {            if(a[l]==a[r])            {                if(r-l+1>chang)                {                    chang=r-l+1;                    f=l+1;                }            }            else                break;        }    }    for(int i=0;i<m;i++)//偶数     {        int l,r;        for(l=i,r=i+1;l>=0&&r<=m;l--,r++)        {            if(a[l]==a[r])            {                if(r-l+1>chang)                {                    chang=r-l+1;                    f=l+1;                }            }            else                break;        }    }}void outs(){    cout<<chang<<endl;    int cnt=0;    for(int i=0;i<n;i++)    {        if(isalpha(s[i]))            cnt++;        if(cnt==f)        {            int t=0;            for(int j=0;t<chang;j++)            {                putchar(s[i+j]);                if(isalpha(s[i+j]))                {                    t++;                }            }            break;        }    }}int main(){    //freopen("in.txt","r",stdin);    Init();    solve();    outs();    return 0;}

细节

1、字符串处理问题
a、末尾0的位置下标=字符串长度
b、手动读入字符串的时候,用n++,然后最后在n的位置补上0,则刚刚好
c、是’\0’不是’/0’
d、记得从0开始处理
(代码的很多函数应该是cctype里面的,我故意去掉之后还是通过了,当然多写点头文件没什么毛病)

关于逗号

逗号的含义:一个优先级很低的位运算符。
从左到右一次执行语句并且返回最后一个语句的值,千万不要误以为和&&相同,for循环里面的中间那一重就不要用。
逗号是一个语句,意味着可以在if或者循环下面减少括号,当然必须有返回值的语句才能这么用,continue这些就不行

收获

1、回文串判断
a、直接搜索
b、dp
2、字符串的处理
3、关于逗号

再说一句

这道题我很早就尝试做过了,当时的思路很好,但是因为代码能力确实没有实现出来,如今再来做倒是畅快了不少,也没有想象的难,但是还是有很多技巧的

原创粉丝点击