【校内互测】回文词

大意:给出一篇文章(包括字母非字母以及换行符),判断长度大于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);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值