问题 A: 【字符串】最长回文子串

题目描述

        输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同。如abba和yyxyy。在判断回文时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占据单独的一行。应该输出最长的回文串,如果有多个,输出起始位置最靠左的。

输入

一行字符串,字符串长度不超过5000。

输出

字符串中的最长回文子串。

样例输入 Copy

Confuciuss say:Madam,I'm Adam.

样例输出 Copy

Madam,I'm Adam
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int p[5005], cnt, maxstart, maxend;//保存小写后每个字母在原来字符串的位置
string lower(string s) { //保存只有小写的串并计算出p数组
	string low = "";
	int len = s.length();
	cnt = 0;
	for(int i = 0; i < len; i++) {
		if((s[i] >= 'A' && s[i] <= 'Z')||(s[i] >= 'a' && s[i] <= 'z')||(s[i] >= '0' && s[i] <= '9')) {
			if(s[i] >= 'A' && s[i] <= 'Z') {
				low.push_back(s[i] + 32);
			} else {
				low.push_back(s[i]);
			}
			p[cnt++] = i;
		}
	}
	return low;
}
void cal(string low) {
	int len = low.length();
	int dp[len][len];//i到j是否是回文串的标记数组
	memset(dp, 0, sizeof(dp));
	int ans = -1;//最长回文串长度
	maxstart = 0, maxend = 0;
	for(int i = 0; i < len; i++) {
		dp[i][i] = 1;
		if(i < len - 1) {
			if(low[i] == low[i + 1]) {
				dp[i][i + 1] = 1;
				if(ans < 2) {
					ans = 2;
					maxstart = i;
					maxend = i + 1;
				}
			}
		}
	}
	for(int L = 3; L <= len; L++) { //枚举字串的长度
		for(int i = 0; i + L - 1 < len; i++) { //枚举字串的起始端点
			int j = i + L - 1;//字串右端点
			if(low[i] == low[j] && dp[i + 1][j - 1] == 1) {
				dp[i][j] = 1;
				if(ans < L) {
					ans = L;
					maxstart = i;
					maxend = j;
				}
			}
		}
	}
}
int main(int argc, char** argv) {
	string s;
	while(getline(cin, s)) {
		memset(p, -1, sizeof(p));
		string low = lower(s);
		cal(low);
		for(int i = p[maxstart]; i <= p[maxend]; i++) {
			cout << s[i];
		}
		cout << endl;

	}
	return 0;
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值