leetcode-Longest Palindromic Substring

首先解释题目的意思:

 Palindromic Substring是“回文”的意思。

什么是回文呢?它是一种修辞手法。如“凤落梧桐梧落凤”这句话就是用了回文的修辞。

这道题目的意思是让你求一个字符串中的最长回文串,如“ababc”中最长回文串是“aba”.

暴力方法:时间复杂度O(n^2),空间复杂度O(1)(读了leetcode上的一篇文章后发现,还有更暴力的方法,时间复杂度是O(n^3),该方法直接判断源字符串的每个子字符串是不是回文。。本菜突然觉得进步了一点点。)

思路:分别以每个字符为中心,遍历以其为中心的字符串是不是回文,并取最长回文。下面举一个例子

str = abab

以str[0](即第一个a)为中心,最长扩展半径是0(因为它已经是左边界了,以它为中心的字符串长度最大只能是1),最长回文只能是a;

以str[1](即第一个b)为中心,最长扩展半径是1(因为它的左右两边都有字符,但是以它为中心,最多只能扩展1位,因为如果扩展2位,左边就越界了,所以以它为中心的子字符串的最大长度是3),最长回文是aba;

以str[2](即第二个a)为中心,最长扩展半径是1(以它为中心,最多只能扩展1位,因为如果扩展2位,右边就越界了,所以以它为中心的子字符串的最大长度是3),最长回文是bab;

以str[3](即第二个b)为中心,最长扩展半径是0(因为它已经是右边界了,以它为中心的字符串长度最大只能是1),最长回文只能是b;

检测最长回文的思想:首先需要分类,一类是最长回文字符串长度为奇数,另一类是长度为偶数(上面分析的只是最长回文字符串长度为奇数的情况),具体如何检测,情况代码。

代码如下:

char* longestPalindrome(char* s) {

//最直观的方法——用每个点做回文终点,遍历所有可能性,时间复杂度为n^2

//稍微改进的方法——从中间点开始找,记录当前找到的最大回文串长度,

//如s长为5,中点最大回文长3,其它点就不用找了

int index_max, index_current;

int srcLen = 0;

bool oddlen = true;

int maxlen = 0;

while (s[srcLen] != ‘\0’)

{

srcLen++;

}

int srcLen_d1 = srcLen – 1;

int radius_posibal_odd, radius_posibal_even;

int i = 0;

for (index_current = 0; index_current < srcLen; index_current++)

{

int len, substrcount;

radius_posibal_odd = index_current>(srcLen – index_current – 1) ? srcLen – index_current – 1 : index_current;

radius_posibal_even = index_current + 1 > srcLen – 1 – index_current ? srcLen – 1 – index_current : index_current + 1;

if (maxlen < 1 + radius_posibal_odd * 2)

{

//回文串长度为奇数

i = 1;

len = 0;

substrcount = 0;

while (i <= radius_posibal_odd)

{

if (s[index_current – i] == s[index_current + i])

substrcount++;

else

{

len = substrcount * 2 + 1;

if (len > maxlen)

{

maxlen = len;

oddlen = true;

index_max = index_current;

}

break;

}

i++;

}

len = substrcount * 2 + 1;

if (len > maxlen)

{

maxlen = len;

oddlen = true;

index_max = index_current;

}

}

if (maxlen < radius_posibal_even * 2)

{

//回文串长度为偶数

i = 0;

len = 0;

substrcount = 0;

while (i<radius_posibal_even)

{

if (s[index_current – i] == s[index_current + 1 + i])

substrcount++;

else

{

len = substrcount * 2;

if (len>maxlen)

{

maxlen = len;

oddlen = false;

index_max = index_current;

}

break;

}

i++;

}

len = substrcount * 2;

if (len > maxlen)

{

maxlen = len;

oddlen = true;

index_max = index_current;

}

}

}

int index_rs;

if (oddlen)

{

index_rs = index_max – (maxlen – 1) / 2;

}

else

{

index_rs = index_max – (maxlen / 2 – 1);

}

char *rs = (char*)malloc((maxlen + 1)*sizeof(char));

for (i = 0; i < maxlen; i++)

{

rs[i] = s[index_rs + i];

}

rs[i] = ‘\0’;

return rs;

}

动态规划法:时间复杂度O(n^2),空间复杂度O(n^2),空间复杂度可以优化到O(n)

连接如下:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-i.html

C 0ms解法(其实该方法就是最开始的“暴力方法”的优化,但是给出该方法的人说该方法的时间复杂度是O(n)):

char* longestPalindrome(char* s) {
char *go,*max_start,*left,*right,*re;
int max_length,temp_length;
char *s_end;
s_end = s+strlen(s);
if (strlen(s) == 0) return s;
if (strlen(s) == 1) return s;
for(go = s,max_length = 1;go<s_end;)
{
    if (s_end – go <= max_length * sizeof(char) / 2) break;
    left = go,right = go;
    while(*right==*(right+1)) right++;
    go = right + 1;
    while(left<s_end && left>s && *(left-1) == *(right+1))
    {
        right++;
        left–;
    }
    temp_length = (right-left)/sizeof(char) + 1;
    if(temp_length > max_length) {
        max_start = left;
        max_length = temp_length;
    }
}
re =(char *) malloc(max_length*sizeof(char)+1);
go = re;
while(max_length)
{
    *(go) = *(max_start);
    go++;
    max_start++;
    max_length–;
}
*go = ‘\0’;
return re;

manacher’s 算法:

没搞明白,而且算法速度也没有上面的方法块。。。记录它的原因是因为它需要重新构造一个字符串,目的是为了省去回文串长度为偶数和奇数时算法上的不同。

字符添加方法举例如下:添加前的字符串为abc,添加之后变为#a#b#c#。

具体原理讲解在:

英文原文:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

汉语译文:http://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

点赞