longest palindromic substring(最长回文子串)

题记: 尼玛没想到一个简单的回文字符串这么多的解法。 跪了。 不同的perspective, 看到的问题的不同的结构, 进而会完全影响你解决问题的思路。

注意, substring和subsequence 是有区别的。substring属于subsequence, 但是subsequence 不一定是substring。

给定一个string T = str[0…n-1], 该字符串的一个子串substring就是截取连续的(包括全部)的一部分subT = [i, …j], 其中, 0<= iand j <= n-1。 但是subsequence则是选择相关的字符, 保持其在原字符串中的相对顺序, 然后组成的新的string就是subsequence, 别混淆了。

最长回文子串(LPS)就是从给定的字符串中找出最长的一个子字符串, 这个子字符串从左往右读和从右往左读, 读出的结果是一样的。

例如:aba, a, abba均是回文子串。 在例如, S = "abcbcbb"的LPS 是“bcbcb”。

(方法一) bruteforce的办法: 最简单的办法就是价差字符串的每一个子字符串是否为palindrome or not。 我们可以运行三个loops, 外层两个loops 一个个的选择字符串所有可能的子字符串, 内层循环检查选的该子字符串是否是palindorme的。

#include <string>#include <iostream>using namespace std;/*判断str[i..j]是否为回文串*/bool isPalindrome(string str, int Start, int End) {while(str[Start++] == str[End–] && Start <= End) { }if(str[–Start] != str[++End]) {return false;} else {return true;}}/*返回最长回文子串长度*/string longestPald(string str) {int len = str.length();int longest = 1;if(len == 1) {return str.substr(0, 1);}int longestStart = 0;for(int i = 0; i<len; i++) {for(int j = i + 1; j < len; j++) {if(isPalindrome(str, i, j)) {if(longest < j – i + 1) {longestStart = i;longest = j – i + 1;}//longest = (longest < j-i+1 ? j-i+1: longest);}}}cout << longest << endl;return str.substr(longestStart, longest);}int main() {string s = "forgeeksskeegfor";cout << longestPald(s) << endl;return 0;}运行结果如下:

分析: 时间复杂度: O(n^3)

辅助空间复杂度: O(1)

(方法二) 动态规划的办法: 我们maintain一个boolean的table[n][n], 然后自底向上的方式填充这个table。 如果子字符串str[i, j]是palindrome的 我们就把table[i][j]记为true, 否则就记为false。 为了计算table[i][j], 我们需要首先检查table[i+1][j-1], 如果table[i+1][j-1]是true的, 并且str[i]与str[j]是相同的字符, 我们就记录table[i][j]为true。否则table[i][j]就为false。 更详细的分析见下面:

如果substring(i, j)是palindromic的, 那么substring(i+1, j-1)也是palindromic的。

table[i][j]是palindromic的, 那么几位true。 otherwise, 记为0。

当j – i 比较小的时候, 即为0或者为1, 那么我们很容易知道:

table[i][i] = true, table[i][i+1] = (S[i] == S[j]), 这是base case。

另外, 还有table[i][j] = table[i + 1] [j – 1] && S[i]==S[j]。

table[i][i]如下:

table[i][i+1]如下:

table[i][i+2], table[i][i+3]等等如下:

程序如下:

#include <string>#include <cstring>#include <iostream>using namespace std;string longestPalindromeDP(string s) {  int n = s.length();  int longestBegin = 0;  int maxLen = 1;  bool table[1000][1000];  memset(table, 0, sizeof(table[0][0]) * 1000 * 1000);  // for substring of length 1 are palindrome  for (int i = 0; i < n; i++) {    table[i][i] = true;  }  //check for substring of length 2  for (int i = 0; i < n-1; i++) {    if (s[i] == s[i+1]) {      table[i][i+1] = true;      longestBegin = i;      maxLen = 2;    }  }  // check for lengths greater than 2  // len is the length of substring  for (int len = 3; len <= n; len++) {    // fix the starting index    for (int i = 0; i < n-len+1; i++) {      int j = i+len-1;       // checking for sub-string from ith index to       // jth index iff str[i+1] to str[j-1] is a       // palindrome      if (s[i] == s[j] && table[i+1][j-1]) {        table[i][j] = true;        /*if(len > maxlen) { // 总是成立,, 所以可以去掉这个条件            longestBegin = i;            maxLen = len;        } */        longestBegin = i;        maxLen = len;      }    }  }  return s.substr(longestBegin, maxLen);}int main() {    string s = "forgeeksskeegfor";    cout << longestPalindromeDP(s) << endl;    return 0;}运行结果如下:在你成功地把自己推销给别人之前,你必须百

longest palindromic substring(最长回文子串)

相关文章:

你感兴趣的文章:

标签云: