【注意getline吃空格】第三届ACM/ICPC程序设计知识竞赛—— 又见回文

来源:点击打开链接

求十万个字符以内的回文串,可以采用上一篇中的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;
}


 

 

posted @ 2013-05-26 22:48  javawebsoa  Views(259)  Comments(0Edit  收藏  举报