大意:给出一篇文章(包括字母非字母以及换行符),判断长度大于n的回文词的个数,并将每一个回文词输出(回文中心相同的算一个,且只输出最长的)。注意:判断时忽略非字母字符和大小写,但是输出时全部输出(包括换行符)。
【题解】
枚举回文中心即可,注意回文词个数为奇数或是偶数要分别讨论,读入时要注意用getchar把所有的都读进来(因为不能忽略换行符)。
【代码】
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,len,tmp,head,tail,headloc,tailloc,ans,stj,sto;
char s[50005],ch[50005],x;
bool pd;
int loc[5005];
inline bool ok(int head,int tail,int mid){
for (int i=head;i<=mid;++i)
if (ch[i]!=ch[head+tail-i])
return false;
return true;
}
int main(){
freopen("words.in","r",stdin);
freopen("words.out","w",stdout);
scanf("%d\n",&n);
x=getchar();
while (x!=EOF){
s[++len]=x;
x=getchar();
}
for (int i=1;i<=len;++i)
if (s[i]>='A'&&s[i]<='Z'||s[i]>='a'&&s[i]<='z'){
ch[++tmp]=s[i];
if (ch[tmp]>='A'&&ch[tmp]<='Z') ch[tmp]+=32;
loc[tmp]=i;
}
if (n%2==1) stj=n/2,sto=n/2+1;//如果n为奇数,回文是奇数个的一边最少有n/2个,偶数个的一边最少有n/2+1个
else stj=sto=n/2;//如果n为偶数,回文数是奇数数个的一边最少有n/2个,偶数个的也最少有n/2个
for (int i=stj+1;i<=tmp-stj;++i){
if (i-stj>=1&&i+stj<=tmp){
head=i-stj,tail=i+stj;
pd=false;
while (ok(head,tail,i)){
pd=true;
headloc=loc[head],tailloc=loc[tail];
if (head-1>=1&&tail+1<=tmp) head--,tail++;
else break;
}
if (pd){
ans++;
for (int j=headloc;j<=tailloc;++j)
putchar(s[j]);
printf("\n");
}
}
if (i-sto+1>=1&&i+sto<=tmp){
head=i-sto+1,tail=i+sto;
pd=false;
while (ok(head,tail,i)){
pd=true;
headloc=loc[head],tailloc=loc[tail];
if (head-1>=1&&tail+1<=tmp) head--,tail++;
else break;
}
if (pd){
ans++;
for (int j=headloc;j<=tailloc;++j)
putchar(s[j]);
printf("\n");
}
}
}
printf("%d\n",ans);
}