USACO-Calf Flac
http://ace.delos.com/usacoprob2?a=I1dC0kaErvZ&S=calfflac
求文章的最大回文字串,暴搜就可以了。可以算一下时间复杂度,O()=20000*2000=40000000,四千万而已,绝对不超时,当然前提是不用string,若用string,可能会超时,这个我没有试过了。
主要是枚举回文串的中值,然后用两个指针向中值的两边尽可能扩展,然后记录最大的长度就行了。网上的解题报告更多的是用两个数组工作,这个当然也是一个好方法,但是输出时是个麻烦。所以我直接用一个数组,在扩展时判断是否为字母,而输出时就简单很多了。
#include <iostream> #include <string.h> #include <string> #include <cstdio> #include <ctype.h> //isalpha函数的定义头文件 using namespace std; char s[30000]; void search(int len,int &sum,int &ll,int &rr) { while (ll>0 && rr<len) //指针的移动必须在文章中,不可超出范围了 { while (ll>0 && !isalpha(s[ll])) ll--; while (rr<len && !isalpha(s[rr])) rr++; if (s[ll]==s[rr] || (s[ll]-'a'+'A')==s[rr] || (s[ll]-'A'+'a'==s[rr])) { sum+=2; ll--; rr++; } else return; //若二者不相等,明显回文到此结束 } } int main() { freopen("calfflac.in","r",stdin); freopen("calfflac.out","w",stdout); int len=0; char ss[30000]; while (gets(ss)) { if (len) s[++len]='\n'; for (int i=0;ss[i];i++) s[++len]=ss[i]; } s[++len]='\0'; int max=0,start=0,endd=0; for (int i=1;i<=len;i++) if (isalpha(s[i])) { //处理回文串长度是偶数的情况 int even=0; int l=i-1,r=i+1; while (l>0 && !isalpha(s[l])) l--; while (r<len && !isalpha(s[r])) r++; if (s[l]==s[i] || (s[l]-'a'+'A')==s[i] || (s[l]-'A'+'a'==s[i])) { even=2; l--; search(len,even,l,r); if (even>max) { max=even; start=l+1; endd=r-1; } } else if (s[r]==s[i] || (s[r]-'a'+'A')==s[i] || (s[r]-'A'+'a'==s[i])) { even=2; r++; search(len,even,l,r); if (even>max) { max=even; start=l+1; endd=r-1; } } //处理奇数情况 l=i-1; r=i+1; int odd=1; search(len,odd,l,r); if (odd>max) { max=odd; start=l+1; endd=r-1; } } //因为之前记录时没有忽略非字母的字符,所以现在要修改一下 while (!isalpha(s[start])) start++; while (!isalpha(s[endd])) endd--; cout<<max<<endl; for (int i=start;i<=endd;i++) cout<<s[i]; cout<<endl; return 0; }
当然,我的程序写得不怎样,太多重复的代码,但是如果改为函数,要传递的参数又过多,得不偿失了。
这题自己出数据太简单了,所以这题基本上要秒杀的。。。。