问题 A: 【字符串】最长回文子串
[命题人 : 外部导入]
时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同。如abba和yyxyy。在判断回文时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占据单独的一行。应该输出最长的回文串,如果有多个,输出起始位置最靠左的。
输入
一行字符串,字符串长度不超过5000。
输出
字符串中的最长回文子串。
样例输入 Copy
Confuciuss say:Madam,I’m Adam.
样例输出 Copy
Madam,I’m Adam
提示
**样例说明:**Madam,I’m Adam去掉空格、逗号、单引号、忽略大小写为MADAMIMADAM,是回文。
一道不怎么用到脑力的题目,卡了半小时,回文串的细节就直接用回文串的模板就行,他的状态公式即是判断 两个字符是否相等,相等时向内左右各收缩一格,判断dp的状态,是则1,否则0;注意判断的过程需要按3 4 5不断的间隔,原因是:举个例子,从0 1 2 3 4 下标看,04的比较需要13,所以间隔为4的需要间隔为3 的提前铺垫。dp的预处理初始化要注意dp[i][i]dp[i][i+1]为1或0.
下面讲讲此题,把数字和字母的字符用一个新的数字a保持,记得用hasha数组保存这个字符对应于原数组的位置下标,然后用结构体对象R保存每次遍历得到的最长串的位于a数组的下标。
题目不难,只要掌握了基本的回文串,套个框框下去就轻松解决!
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char a[5000];
char a_tmp[5000];
int dp[5000][5000];
int hasha[5000];//记录原始下标 a对应原来a_tmp的下标
struct record {
int x;
int y;
int changdu;
} R;
char Toup(char aa) {
if(isdigit(aa)) return aa;
if(aa >= 'a'&&aa <= 'z') {
return aa-32;
} else {
return aa;
}
}
int main() {
cin.getline(a_tmp,5000);
int lena_tmp = strlen(a_tmp);
int num = 0;
for(int i = 0; i < lena_tmp; i++) {
char temp = a_tmp[i];
if(isalpha(temp)||isdigit(temp)) {
hasha[num] = i;//记录原始下标
//千万不可以把它改为都是大写,之后无法复原到原来对应的大小写的原数组位置!!
//遍历判断时进行toupper就可以了
a[num++] = temp;
}
}
a[num] = '\0';
int lena = strlen(a);
memset(dp,0,sizeof(dp));
int ans = 1;
R.x = 0;
R.y = 0;
R.changdu = 1;
//a是带有大小写的 判断的时候注意
char tempi,tempj;
for(int i = 0 ; i < lena; i++) {
dp[i][i] = 1;
tempi = Toup(a[i]);//注意数字
tempj = Toup(a[i+1]);
if(tempi==tempj&&i<lena-1) {
dp[i][i+1] = 1;
ans = 2;
R.x = i;
R.y = i + 1;
R.changdu = 2;
}
}
//a是带有大小写的 判断的时候注意
for(int L = 3; L <= lena; L++) {
for(int i = 0; i + L - 1 < lena; i++) {
int j = i + L - 1;
tempi = Toup(a[i]);//注意数字
tempj = Toup(a[j]);
if(tempi==tempj&&dp[i + 1][j - 1]==1) {
dp[i][j] = 1;
ans = L;
if(L>R.changdu) {
R.x = i;
R.y = j;
R.changdu = L;
}
}
}
}
// for(int i = 0; i <= lena - 1; i++) {
// printf("%c",a[i]);
// }
// printf("%d",ans);
// for(int i = R.x; i <= R.y; i++) {
// printf("%c",a[i]);
// }
// printf("\n%d\n",ans);
//通过hasha的下标 即原始串的位置,
int start = hasha[R.x];
int end = hasha[R.y];
for(int i = start; i <= end; i++){
printf("%c",a_tmp[i]);
}
return 0;
}