
Donald W. answered 04/01/22
Experienced and Patient Tutor for Math and Computer Science
You didn't specify a language, so here's a DP implementation using C++:
vector<vector<int>> dp;
bool isPalindrome(string s, int start, int end) {
if (start > end) {
return true;
}
int dpval = dp[start][end];
if (dpval >= 0) {
return dpval == 1;
}
bool ret = s[start] == s[end] && isPalindrome(s, start+1, end-1);
dp[start][end] = ret ? 1 : 0;
return ret;
}
vector<string> longestPalindromeSubstrings(string s) {
int size = s.length();
dp = vector<vector<int>>(size, vector<int>(size, -1));
int maxLength = 1;
vector<string> results;
for (int i=0; i<size; i++) {
for (int j=i; j<size; j++) {
if (isPalindrome(s, i, j)) {
maxLength = max(maxLength, j-i+1);
}
}
}
for (int i=0; i<size; i++) {
for (int j=0; j<size; j++) {
if (dp[i][j] == 1 && j-i+1 == maxLength) {
results.push_back(s.substr(i, j-i+1));
}
}
}
return results;
}
The runtime is O(n2) because the DP table is n x n and each item in that table only needs to be calculated once and each calculation is O(1).
Also interesting to note that using DP isn't the most efficient algorithm here. I was able to get better performance using this code that doesn't use DP:
bool isPalindrome(string s, int start, int end) {
while (start < end) {
if (s[start] != s[end]) {
return false;
}
start++;
end--;
}
return true;
}
vector<string> longestPalindromeSubstrings(string s) {
int size = s.length();
int maxLength = 1;
vector<string> results;
for (int i=0; i<size-maxLength+1; i++) {
for (int j=size-1; j>=i+maxLength-1; j--) {
if (isPalindrome(s, i, j)) {
if (j - i + 1 > maxLength) {
maxLength = j - i + 1;
results.clear();
}
results.push_back(s.substr(i, j - i + 1));
break;
}
}
}
return results;
}