5. 最长回文子串
给定一个字符串
s,找到s中最长的回文子串。你可以假设s的最大长度为 1000。
步骤:
- 对于空字符串、长度为1或2的字符串进行特判;
- 申请二维数组
P用于标记s[i]到s[j]之间的字符串是否为回文; - 初始化
P[i][i]和P[i][i+1]; P[i][i+k]=(P[i+1][i+k-1] && s[i] == s[i+k]),k从2到len(s)-1循环,i从0开始循环。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * longestPalindrome(char * s)
{
// Step 1
if (s == NULL)
return NULL;
int len = strlen(s);
if (len == 1)
return s;
else if (len == 2)
{
if (s[0] == s[1])
return s;
else
return NULL;
}
// Step 2 and 3
int left, right;
int **P = (int**)malloc(sizeof(int*) * len);
for (int i = 0; i < len; i++)
{
P[i] = (int*)malloc(sizeof(int) * len);
P[i][i] = 1;
}
for (int i = 0; i < len - 1; i++)
{
if (s[i] == s[i + 1])
{
P[i][i + 1] = 1;
P[i + 1][i] = 1;
}
else
{
P[i][i + 1] = 0;
P[i + 1][i] = 0;
}
}
// Step 4
for (int k = 2; k < len; k++)
{
for (int i = 0; i + k < len; i++)
{
int j = i + k;
P[i][j] = (P[i + 1][j - 1] && s[i] == s[j]);
if (P[i][j])
{
left = i;
right = j;
}
}
}
// Output result;
char* result = (char*)malloc(sizeof(char) * (right - left + 2));
for (int i = left; i <= right; i++)
result[i - left] = s[i];
result[right - left + 1] = '\0';
for (int i = 0; i < len; i++)
free(P[i]);
return result;
}
int main()
{
char str[1000];
scanf("%s", str);
printf("%s", longestPalindrome(str));
return 0;
}
拓展:一个相似的问题
给定一个字符串 S ,最少需要几次增删改操作可以把 S 变成一个回文字符串?一次操作可以在任意位置插入一个字符,或者删除任意一个字符,或者把任意一个字符修改成任意其他字符。
请编写一个程序,计算最少的操作次数并输出。 输入格式: 字符串 S,S的长度不超过100, 只包含’A’-‘Z’。 输出格式:最少的操作次数。
思路:用相同的方法遍历字符串,遍历时记录累加最少的修改次数。即:
P[i][i] = 0,其他初始化为0x3f3f3f3f;s[i] == s[j] && P[i][i + k] = min(P[i][j + k], P[i + 1][i + k - 1])s[i] !=s[j] && P[i][j]=min(P[i][j],P[i+1][j]+1,P[i][j-1]+1,P[i+1][j-1]+1)
本文详细介绍了如何寻找字符串中最长的回文子串,包括算法步骤和C语言实现。通过二维数组标记回文子串,实现了高效查找。同时,文章还探讨了将任意字符串转化为回文字符串所需的最少操作次数。
996

被折叠的 条评论
为什么被折叠?



