来源:点击打开链接
求十万个字符以内的回文串,可以采用上一篇中的manacher算法,另外要判断空格,把无关的空格去掉。
按这个思路,WA了两次,原因是getchar()的时候会把第一个样例的第一个字符给吃掉,但如果不加,需要按两下回车才有结果,与题目不符,只能动手判断一下了。。
// 原串最大长度N
// 返回最大回文字串 res
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <iostream>
#include <ctype.h>
using namespace std;
const int N = 200009;
int rid[N<<2];
string clear_space(string s)
{
string res;
for(int i=0;i<s.length();i++)
{
if(isblank(s[i]))
{
continue;
}
else if(isupper(s[i]))
{
res+=s[i]+32;
}
else if(islower(s[i]))
{
res+=s[i];
}
}
return res;
}
string manacher(string s){
string t, res;
int L = s.size();
// init
t += '?';
for(int i = 0; i < L; i++)
t += '#', t += s[i];
t += "#*";
// getrid
for(int i=1,j=0,k,End=(int)t.size();i<End;){
while( t[i-j-1]==t[i+j+1] ) j++;
rid[i] = j;
for(k=1;k<=j&&(rid[i-k]!=rid[i]-k);k++)
rid[i+k] = min( rid[i-k], rid[i]-k );
i += k;
j = max( 0,j-k );
}
// Max
int m = 0, pos;
for(int i = 1; i < (int)t.size(); i++){
if( m < rid[i]*2+(t[i]!='#') )
m = rid[i]*2+(t[i]!='#'), pos = i;
}
for(int i = pos-rid[pos]; i <= pos+rid[pos]; i++){
if( t[i] != '#' ) res += t[i];
}
return res;
}
int main()
{
string tar;
string res,ret;
char z;
int pos=0;
z=getchar();
while(getline(cin,tar))
{
if(z!='\n' && pos==0)
{
tar.insert(tar.begin(),z);
pos=1;
}
//cout<<tar<<endl;
if(tar=="2013")
break;
ret=clear_space(tar);
res=manacher(ret);
if(res==ret || res==tar)
{
cout<<"YES"<<endl;
}
else
cout<<"NO"<<endl;
}
return 0;
}