Codelet Keep code simple stupid

Longest Palindromic Substring

Question

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

Solution

#include <string>
#include <utility>
using namespace std;

class Solution {
public:
  typedef string::const_iterator Iter;
  typedef pair<Iter, Iter> Range;

  Range longerPalindrome(Range range, Range cursor, Range prev) {
    Iter b = range.first;
    Iter e = range.second;
    Iter l = cursor.first;
    Iter r = cursor.second;
    while (l >= b && r < e && *l == *r) {
      l--;
      r++;
    }
    Range result = make_pair(l + 1, r);
    if (result.second - result.first > prev.second - prev.first) {
      return result;
    } else {
      return prev;
    }
  }

  string longestPalindrome(string s) {
    Range range = make_pair(s.begin(), s.end());
    Range result = make_pair(s.begin(), s.begin());
    for (Iter i = range.first; i < range.second; i++) {
      result = longerPalindrome(range, make_pair(i, i), result);
      result = longerPalindrome(range, make_pair(i, i + 1), result);
    }
    return string(result.first, result.second);
  }
};
  • Dynamic programming
i:j        
0,0 0,1 0,2 0,3 0,4
  1,1 1,2 1,3 1,4
    2,2 2,3 2,4
      3,3 3,4
        4,4
have j >= i
all (i:j) where i == j     -> true
all (i:j) where i == j - 1 -> compare(i,j)
==>
(i:j) -> compare(i,j) and (i+1:j-1)
# (i+1:j-1) is at the left-down of (i:j)
longest -> (i:j) where j - i == max
# the greater j - i the more right-up for (i:j)
#include <string>
using namespace std;

class Solution {
public:
  string longestPalindrome(string s) {
    const int size = s.length();
    bool dp[1000][1000];
    int begin, length;
    // For substr length == 1
    for (int i = 0; i < size; i++) {
      dp[i][i] = true;
      begin = i;
      length = 1;
    }
    // For length == 2
    for (int i = 0; i < size - 1; i++) {
      bool result = s[i] == s[i + 1];
      dp[i][i + 1] = result;
      if (result) {
        begin = i;
        length = 2;
      }
    }
    // For length >= 3
    for (int len = 3; len <= size; len++) {
      for (int i = 0; i < size - len + 1; i++) {
        int j = i + len - 1;
        bool result = dp[i + 1][j - 1] && s[i] == s[j];
        dp[i][j] = result;
        if (result) {
          begin = i;
          length = len;
        }
      }
    }
    return s.substr(begin, length);
  }
};

Test Cases

Solution sol;

TEST(LPS, Case1) {
  string s = "abbaccab";
  string r = sol.longestPalindrome(s);
  ASSERT_EQ("baccab", r);
}

TEST(LPS, Case2) {
  string s = "a";
  string r = sol.longestPalindrome(s);
  ASSERT_EQ("a", r);
}

TEST(LPS, Case3) {
  string s = "abb";
  string r = sol.longestPalindrome(s);
  ASSERT_EQ("bb", r);
}

TEST(LPS, Case4) {
  string s = "bbc";
  string r = sol.longestPalindrome(s);
  ASSERT_EQ("bb", r);
}