Longest Palindromic Substring using Dynamic Programming
Given a string s, the task is to find the longest substring which is a palindrome. If there are multiple answers, then return the first occurrence of the longest palindromic substring from left to right.
Examples:
Input: s = "aaaabbaa"
Output: "aabbaa"
Explanation: The longest palindromic substring is "aabbaa".Input: s = "geeks"
Output: "ee"Input: s = "abc"
Output: "a"
Input: s = ""
Output: ""
Approach:
The idea is to use Dynamic Programming to store the status of smaller substrings and use these results to check if a longer substring forms a palindrome. If we know the status (i.e., palindrome or not) of the substring ranging [i, j], we can find the status of the substring ranging [i-1, j+1] by only matching the character s[i-1] and s[j+1].
- If the substring from i to j is not a palindrome, then the substring from i-1 to j+1 will also not be a palindrome. Otherwise, it will be a palindrome only if s[i-1] and s[j+1] are the same.
Based on this fact, we can create a 2D table (say dp[][] which stores status of substring s[i...j] ), and check for substrings with length from 1 to n. For each length find all the substrings starting from each character i and find if it is a palindrome or not using the above idea. The longest length for which a palindrome formed will be the required answer.
Illustration:
Follow the below illustration for a better understanding.
Consider the string "geeks". Below is the structure of the table formed and from this, we can see that the longest substring is 2.
Step by step approach:
- Maintain a boolean dp[n][n] that is filled in a bottom-up manner.
- Fill the table initially for substrings of length = 1 and length = 2 (All substrings of length 1 are palindrome and all substrings of length 2 with same characters are also palindrome).
- Iterate for all possible lengths from 3 to n:
- For each length iterate from i = 0 to n-length, find the end of the substring j = i+length-1. To calculate table[i][j], check the value of table[i+1][j-1]:
- if the value is true and str[i] is the same as str[j], then we make table[i][j] true.
- Otherwise, the value of table[i][j] is made false.
- For each length iterate from i = 0 to n-length, find the end of the substring j = i+length-1. To calculate table[i][j], check the value of table[i+1][j-1]:
- Update the longest palindrome accordingly whenever a new palindrome of greater length is found.
// C++ program to find the longest
// palindromic substring.
#include <bits/stdc++.h>
using namespace std;
// Function to find the longest palindrome substring
string longestPalindrome(string &s) {
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n, false));
int start = 0, maxLen = 1;
// All substrings of length 1 are palindromes
for (int i = 0; i < n; ++i)
dp[i][i] = true;
// Check for sub-string of length 2
for (int i = 0; i < n - 1; ++i) {
if (s[i] == s[i + 1]) {
dp[i][i + 1] = true;
if (maxLen<2) {
start = i;
maxLen = 2;
}
}
}
// Check for lengths greater than 2
for (int k = 3; k <= n; ++k) {
for (int i = 0; i < n - k + 1; ++i) {
int j = i + k - 1;
if (dp[i + 1][j - 1] && s[i] == s[j]) {
dp[i][j] = true;
if (k > maxLen) {
start = i;
maxLen = k;
}
}
}
}
return s.substr(start, maxLen);
}
int main() {
string s = "aaaabbaa";
cout << longestPalindrome(s) << endl;
return 0;
}
// Java program to find the longest
// palindromic substring.
import java.util.*;
class GfG {
// Function to find the longest palindrome substring
static String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
int start = 0, maxLen = 1;
// All substrings of length 1 are palindromes
for (int i = 0; i < n; ++i)
dp[i][i] = true;
// Check for sub-string of length 2
for (int i = 0; i < n - 1; ++i) {
if (s.charAt(i) == s.charAt(i + 1)) {
dp[i][i + 1] = true;
if (maxLen < 2) {
start = i;
maxLen = 2;
}
}
}
// Check for lengths greater than 2
for (int k = 3; k <= n; ++k) {
for (int i = 0; i < n - k + 1; ++i) {
int j = i + k - 1;
if (dp[i + 1][j - 1] && s.charAt(i) == s.charAt(j)) {
dp[i][j] = true;
if (k > maxLen) {
start = i;
maxLen = k;
}
}
}
}
return s.substring(start, start + maxLen);
}
public static void main(String[] args) {
String s = "aaaabbaa";
System.out.println(longestPalindrome(s));
}
}
# Python program to find the longest
# palindromic substring.
# Function to find the longest palindrome substring
def longestPalindrome(s):
n = len(s)
dp = [[False] * n for _ in range(n)]
start, maxLen = 0, 1
# All substrings of length 1 are palindromes
for i in range(n):
dp[i][i] = True
# Check for sub-string of length 2
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
if maxLen < 2:
start = i
maxLen = 2
# Check for lengths greater than 2
for k in range(3, n + 1):
for i in range(n - k + 1):
j = i + k - 1
if dp[i + 1][j - 1] and s[i] == s[j]:
dp[i][j] = True
if k > maxLen:
start = i
maxLen = k
return s[start:start + maxLen]
if __name__ == "__main__":
s = "aaaabbaa"
print(longestPalindrome(s))
// C# program to find the longest
// palindromic substring.
using System;
class GfG {
// Function to find the longest palindrome substring
static string longestPalindrome(string s) {
int n = s.Length;
bool[,] dp = new bool[n, n];
int start = 0, maxLen = 1;
// All substrings of length 1 are palindromes
for (int i = 0; i < n; ++i)
dp[i, i] = true;
// Check for sub-string of length 2
for (int i = 0; i < n - 1; ++i) {
if (s[i] == s[i + 1]) {
dp[i, i + 1] = true;
if (maxLen < 2) {
start = i;
maxLen = 2;
}
}
}
// Check for lengths greater than 2
for (int k = 3; k <= n; ++k) {
for (int i = 0; i < n - k + 1; ++i) {
int j = i + k - 1;
if (dp[i + 1, j - 1] && s[i] == s[j]) {
dp[i, j] = true;
if (k > maxLen) {
start = i;
maxLen = k;
}
}
}
}
return s.Substring(start, maxLen);
}
static void Main(string[] args) {
string s = "aaaabbaa";
Console.WriteLine(longestPalindrome(s));
}
}
// JavaScript program to find the longest
// palindromic substring.
// Function to find the longest palindrome substring
function longestPalindrome(s) {
const n = s.length;
const dp = Array.from({ length: n }, () => Array(n).fill(false));
let start = 0, maxLen = 1;
// All substrings of length 1 are palindromes
for (let i = 0; i < n; ++i)
dp[i][i] = true;
// Check for sub-string of length 2
for (let i = 0; i < n - 1; ++i) {
if (s[i] === s[i + 1]) {
dp[i][i + 1] = true;
if (maxLen < 2) {
start = i;
maxLen = 2;
}
}
}
// Check for lengths greater than 2
for (let k = 3; k <= n; ++k) {
for (let i = 0; i < n - k + 1; ++i) {
const j = i + k - 1;
if (dp[i + 1][j - 1] && s[i] === s[j]) {
dp[i][j] = true;
if (k > maxLen) {
start = i;
maxLen = k;
}
}
}
}
return s.substring(start, start + maxLen);
}
//Driver code
const s = "aaaabbaa";
console.log(longestPalindrome(s));
Output
aabbaa
Time Complexity: O(n^2)
Auxiliary Space: O(n^2)
Related Articles: