您的位置:首页 > 其它

LeetCode OJ-5.Longest Palindromic Substring(最长回文子串)

2016-12-27 14:31 591 查看

LeetCode OJ-5. Longest Palindromic Substring(最长回文子串)

题目描述

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.


Example:

Input: "cbbd"

Output: "bb"


题目理解

​ 题目是要求解最长的回文子串,回文串说的是正着写和反着写结果都是一样的字符串,具体可以看个例子:”bab”就是一个回文串,”aa”也是一个回文串。形式则是第1个字符与第n个字符相等,第2个字符与第n - 1个字符相等,第3个字符与第n - 2个字符相等,以此类推。

时间复杂度为O(n^3)的暴力解法

​ 简单的解法可以从回文串的基本形式想到,可以从某个子串的起始与结束位置向中间渐渐靠拢,若出现不相等的情况,则说明这个子串不可能是回文串。由此可以得到一个时间复杂度为O(n^3)的解法,其中起始位置在最外层循环迭代,而结束位置这里不直接进行迭代,而是在第二层进行子串长度的迭代,则结束位置则为len - 1,最内层循环则是由两边向中间靠拢去判断是否为回文串。PS: 这个解法会超时,仅是提供一种思路。具体代码如下:

int get_longest_palindromic_substr(const char *str, int *start, int *end,
size_t sz)
{
int res = 0;
int i, j;
int k, l;
for (i = 0; i < sz; ++i) {
for (j = 1; j < sz && i + j < sz; ++j) {
k = i;
l = j;
while (k < l) {
if (str[k] == str[l]) {
if (k + 1 < l) {
++k;
--j;
}
else {
break;
}
}
else {
break;
}
}

if (k + 1 == l && str[k] == str[l] && j - i + 1 > res) {
*start = i;
*end = j + 1;   //本来这里应该是j + 1,但若要使用string构造函数中以
//迭代器构造的形式,就需要移动到结束位置后一个位置。
res = j - i + 1;
}
else if (k == l && j - i + 1 > res) {
*start = i;
*end = j + 1;   //本来这里应该是j + 1,但若要使用string构造函数中以
//迭代器构造的形式,就需要移动到结束位置后一个位置。
res = j - i + 1;
}
}
}
return res;
}


时间复杂度为O(n^2)的动态规划解法

​ 使用动态规划可以将时间复杂度降为O(n^2),思路与上面的方法类似,只是引入了一个记录状态的dp数组,空间复杂度提升为O(n^2)。

​ 设dp[i][j]为判断从i到j位置的子串是否为回文串的标志,是则为true,不是则为false。状态方程可写作:

dp[i][j]={ dp[i + 1][j - 1], str[i] == str[j] | dp[i][i], i == j | dp[i][i + 1] str[i] == str[i + 1] }.

​ 对于状态方程的三种状态有如下解释:

当str[i] = str[j]时,dp[i][j]的值由i + 1与j - 1对应的dp值决定,即也是一个从两端向中靠拢判断的过程;

当i = j时,当个的字符自然是回文串,则常为true;

相邻位置的字符构成的子串是否为回文串,则看i和i + 1位置的字符是否相等,相等即为true。



有了上述定义,则可以得到代码,对于一些特殊的处理,代码关键位置有注释可参看:

const int g_kMaxSize = 1001;

int get_longest_palindromic_substr(const char *str, int *start, int *end,
size_t sz)
{
int max_len = 1;
bool dp[g_kMaxSize][g_kMaxSize] = { false };
int i, j;
int len;
*start = 0;
*end = 1;
for (i = 0; i < sz; ++i) {
dp[i][i] = true;
}
for (i = 0; i < sz - 1; ++i) {
if (str[i] == str[i + 1]) {
dp[i][i + 1] = true;
*start = i;
*end = i + 2;   //本来这里应该是i + 1,但若要使用string构造函数中以迭代器构造
//的形式,就需要移动到结束位置后一个位置。
max_len = 2;
}
}
for (len = 3; len <= sz; ++len) {
for (i = 0; i < sz; ++i) {
j = i + len - 1;
if (j < sz && str[i] == str[j] && dp[i + 1][j - 1]) {
dp[i][j] = true;
*start = i;
*end = j + 1;   //本来这里应该是j + 1,但若要使用string构造函数中以
//迭代器构造的形式,就需要移动到结束位置后一个位置。
max_len = len;
}
}
}

return max_len;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息