Description:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example2:
Input: “cbbd”
Output: “bb”
[ 题目链接 ]
测试点检查:
1.输入空串"": 输出也要是空串
2.输入"ac" :输出"a"
3.输入"a" : 输出"a"
4.字符串中包含"aaaa"
5.字符串中包含"sooos"
解题思路:
解法一:
我将回文串分为三种:
第一种是对称式回文串,比如:acddca
第二种是重复式的,比如:aaaaa
第三种是夹心饼干使的:acbca
针对这三种情况来分析
解法二:
马拉车(Maracher)算法
这道题用c语言的马拉车算法反而更耗时
因为需要频繁地申请内存
可能其他语言会更加高效
(JAVA效果比较好)
提交代码:
解法一:
char* longestPalindrome(char* s)
{
int i, j;
int max_len = 0, pos = 0, string_len = 0;
for (i = 0; s[i] != '\0'; i++)
{
int current_len = 0;
if (s[i] == s[i + 1])
{
//重复式回文串:aaaa...
char c = s[i];
j = i + 1;
while (s[j] == c)
j++;
current_len = j - i;
//对称回文串cabbac
for (j = i - 1; j >= 0 && s[2 * i - j + 1] != '\0'; j--)
if (s[j] != s[2 * i - j + 1])
break;
if (2 * (i - j) > current_len)
current_len = 2 * (i - j);
}
//如果当前回文串长度大于最大回文串长度,更新
if (current_len > max_len)
{
pos = j + 1;
max_len = current_len;
}
current_len = 0;
//夹心饼干回文串:acbca
if (s[i] == s[i + 2])
{
for (j = i - 1; j >= 0 && s[2 * i - j + 2] != '\0'; j--)
if (s[j] != s[2 * i - j + 2])
break;
current_len = 2 * i - 2 * j + 1;;
}
//如果当前回文串长度大于最大回文串长度,更新
/*更新2次的原因是,可能子字符串即满足对称回文串也满足夹心饼干
回文串,所以更新两次,选取更长的*、
if (current_len > max_len)
{
pos = j + 1;
max_len = current_len;
}
}
//创建新的最长回文串子串
//如果最大长度还是0的话可能是空串或者没有回文串
if (max_len == 0)
{
//空串
if (s[0] == '\0') return s;
char* substring = (char*)malloc(2 * sizeof(char));
substring[0] = s[0];
substring[1] = '\0';
return substring;
}
else
{
char* substring = (char*)malloc((max_len + 1) * sizeof(char));
for (i = pos, j = 0; i < (pos + max_len); i++, j++)
substring[j] = s[i];
substring[j] = '\0';
//printf("%s\n", substring);
return substring;
}
}
解法二:马拉车
char* longestPalindrome(char* s)
{
int i, j, k, string_len = 0;
//计算数组长度
for (i = 0; s[i] != '\0'; i++)
string_len++;
//创建新的马拉车数组,数组长度是2*string_len+3
char* mana_string = (char *)malloc((2 * string_len + 3) * sizeof(char));
mana_string[0] = '$';
for (i = 0, k = 1; i < string_len; i++, k++)
{
mana_string[k++] = '#';
mana_string[k] = s[i];
}
mana_string[k++] = '#';
mana_string[k] = '\0';
printf("%s", mana_string);
//创建回文半径数组radius[],数组长度是2*string_len+1
int *radius = (int *)malloc((2 * string_len + 1) * sizeof(int));
int max_right = 2, max_center = 1, max_radius = 1;
radius[0] = 0;
radius[1] = 1;
for (i = 2; mana_string[i] != '\0'; i++)
{
if (max_right - i > radius[2 * max_center - i])
radius[i] = radius[2 * max_center - i];
else
{
radius[i] = 1; //可再编辑?
while (mana_string[i + radius[i]] == mana_string[i - radius[i]])
radius[i]++;
if (radius[i] >= max_radius)
{
max_radius = radius[i];
max_center = i;
max_right = i + radius[i];
}
}
}
//创建最长回文串字符串
int substring_len = (2 * max_radius - 1) / 2;
char* substring = (char*)malloc(substring_len * sizeof(int));
int start = (max_center - max_radius + 1) / 2;
int end = (max_center + max_radius - 3) / 2;
for (i = start, j = 0; i <= end; i++, j++)
substring[j] = s[i];
substring[j] = '\0';
printf("%s", substring);
return substring;
}
解法二:马拉车(JAVA实现)
class Solution {
public String longestPalindrome(String s) {
char[] str=new char[2*s.length()+2];
str[0]='$';
for(int i=0;i<s.length();i++) {
str[2*i+1]='#';
str[2*i+2]=s.charAt(i);
}str[str.length-1]='#';
// manacher
int center=1,p,maxCenter=0;
int[] radius=new int[2*s.length()+2];
radius[0]=1;radius[1]=1;
for(p=2;p<str.length;p++) {
if(p>=center+radius[center]) {
// the p is out of the range of center
radius[p]=1;
for(int i=p+1;i<str.length&&2*p-i>=0&&str[i]==str[2*p-i];i++)
radius[p]++;
center=p;
if(radius[center]>radius[maxCenter]) maxCenter=p;
}else if(p+radius[2*center-p]<center+radius[center]-1) {
// the p is in the range of center
radius[p]=radius[2*center-p];
}else {
// the p is in the range of center, but the range of p can be farther
radius[p]=Math.max(center+radius[center]-p,1);
for(int i=center+radius[center];i<str.length&&2*p-i>=0&&str[i]==str[2*p-i];i++)
radius[p]++;
center=p;
if(radius[center]>radius[maxCenter]) maxCenter=p;
}
}
return s.substring((maxCenter-radius[maxCenter])/2,(maxCenter+radius[maxCenter]-2)/2);
}
}