Longest Palindromic Substring | Set 1
Given a string, find the longest substring which is palindrome. For example, if the given string is “forgeeksskeegfor”, the output should be “geeksskeeg”.
Method 1 ( Brute Force )
The simple approach is to check each substring whether the substring is a palindrome or not. We can run three loops, the outer two loops pick all substrings one by one by fixing the corner characters, the inner loop checks whether the picked substring is palindrome or not.
Time complexity: O ( n^3 )
Auxiliary complexity: O ( 1 )
Method 2 ( Dynamic Programming )
The time complexity can be reduced by storing results of subproblems. The idea is similar to this post. We maintain a boolean table[n][n] that is filled in bottom up manner. The value of table[i][j] is true, if the substring is palindrome, otherwise false. To calculate table[i][j], we first check the value of table[i+1][j-1], if the value is true and str[i] is same as str[j], then we make table[i][j] true. Otherwise, the value of table[i][j] is made false.
// A dynamic programming solution for longest palindr.
// This code is adopted from following link
// http://www.leetcode.com/2011/11/longest-palindromic-substring-part-i.html
#include <stdio.h>
#include <string.h>
// A utility function to print a substring str[low..high]
void printSubStr( char* str, int low, int high )
{
for( int i = low; i <= high; ++i )
printf("%c", str[i]);
}
// This function prints the longest palindrome substring of str[].
// It also returns the length of the longest palindrome
int longestPalSubstr( char *str )
{
int n = strlen( str ); // get length of input string
// table[i][j] will be false if substring str[i..j] is not palindrome.
// Else table[i][j] will be true
bool table[n][n];
memset( table, 0, sizeof( table ) );
// All substrings of length 1 are palindromes
int maxLength = 1;
for( int i = 0; i < n; ++i )
table[i][i] = true;
// check for sub-string of length 2.
int start = 0;
for( int i = 0; i < n-1; ++i )
{
if( str[i] == str[i+1] )
{
table[i][i+1] = true;
start = i;
maxLength = 2;
}
}
// Check for lengths greater than 2. k is length of substring
for( int k = 3; k <= n; ++k )
{
// Fix the starting index
for( int i = 0; i < n - k + 1 ; ++i )
{
// Get the ending index of substring from starting index i and length k
int j = i + k - 1;
// checking for sub-string from ith index to jth index iff str[i+1]
// to str[j-1] is a palindrome
if( table[i+1][j-1] && str[i] == str[j] )
{
table[i][j] = true;
if( k > maxLength )
{
start = i;
maxLength = k;
}
}
}
}
printf("Longest palindrome substring is: ");
printSubStr( str, start, start + maxLength - 1 );
return maxLength; // return length of LPS
}
// Driver program to test above functions
int main()
{
char str[] = "forgeeksskeegfor";
printf("\nLength is: %d\n", longestPalSubstr( str ) );
return 0;
}
Output:
Longest palindrome substring is: geeksskeeg Length is: 10
Time complexity: O ( n^2 )
Auxiliary Space: O ( n^2 )
We will soon be adding more optimized methods as separate posts.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Intelligent
As suggested by Nikhil, Suffix Tree yields the solution in O(n) instead of going for DP in O(n ^2).
For suffix tree building in O(n) , please see this resource
http://www.cs.ucf.edu/~shzhang/Combio12/lec3.pdf
Instead of dynamic programming we can go with the string matching
1) Lets us assume given string is str
2) Reverse the string and store it in str2
3) Now find the common substring using the suffix tree.
Time Complexity : O(n)
/* A O(n) iterative program for construction of BST from preorder traversal */ #include <stdio.h> #include <stdlib.h> #include <limits.h> //enum bool {true, false}boolean; int LPS(char *str, int beg, int end, int token); int max(int a, int b); int LPS(char *str, int beg, int end, int token){ if(beg > end) return 0; if(beg == end) return 1; if(str[beg] == str[end]) { return max(2+LPS(str, beg+1, end-1, 1), max(LPS(str, beg+1, end, 0),LPS(str, beg, end-1, 0))); } else { if(str[beg-1]!= NULL && str[end+1] != NULL) { if(str[beg-1] == str[end+1]) { if(token == 1) { printf("%d %d --\n", beg-1, end+1); return -2; }} } return max(LPS(str, beg+1, end, 0),LPS(str, beg, end-1, 0)); } } int max(int a, int b){ if(a>=b) return a; else return b; } int main () { char *str="forgeekskeegfor"; int size = 0; char *temp = str; while(*temp!='\0') temp++; size = temp-str; printf("%d\n", size); printf("Size of max palindrome is : %d\n", LPS(str, 0, size-1, 0)); return 0; }i think we can first calculate the length of maximum sized palindrome, and using that length, we can use start = 0 and end = start+length, and increment start till end-length to find maximum sized palindrome.
I have implemented a recursive solution for calculating the length of maximum palindrome without any memoization technique, i think it will be easy to implement that one also.
Thanks
public class LongestPalidromString { static int leftIndex = 0; static int rightIndex = 0; public static void calculatePalidromLength(int left, int right, String str){ int length = 0; while(left >=0 && right < str.length()){ if (str.charAt(left) == str.charAt(right)){ length++; leftIndex = left; rightIndex = right; left--; right++; }else{ break; } } } public static String getMaxPalidromSubString(String input){ int maxLengthSoFar = Integer.MIN_VALUE; String result= null; for(int i = 1 ; i < input.length()-1; i++){ if (input.charAt(i-1) == input.charAt(i+1)){ calculatePalidromLength(i-1, i+1, input); if ((rightIndex - leftIndex)+1 > maxLengthSoFar){ maxLengthSoFar = (rightIndex - leftIndex)+1; result = input.substring(leftIndex, rightIndex); } }else if (input.charAt(i)== input.charAt(i+1)){ calculatePalidromLength(i, i+1, input); if ((rightIndex - leftIndex)+1 > maxLengthSoFar){ maxLengthSoFar = (rightIndex - leftIndex)+1; result = input.substring(leftIndex, rightIndex+1); } } } return result; } public static void main(String[] args){ String result = getMaxPalidromSubString("forgeeksskeegfor"); System.out.println(result); } }Time complexity is still O( n^2 )
#include
#include
using namespace std;
string fun(string s,int i)
{
int l1=0,l2=1,j,k;
string str="";
if(i>0 && s[i]==s[i-1])
{
j=i-2,k=i+1;
while(j>=0 && k<s.length() && s[j]==s[k])
{
j--;
k++;
}
l1=k-j-1;
}
int p=i-1,q=i+1;
//cout<<p<=0 && ql2)
{
for(int t=j+1;t<k;t++)
str+=s[t];
}
else
{
//cout<<"p="<<p<<" q="<<q<<endl;
for(int t=p+1;t<q;t++)
{
str+=s[t];
}
}
// cout<<"str="<<str<>str;
int m=0;
for(int i=0;i<str.length();i++)
{
s=fun(str,i);
//cout<<s< m)
{
m=s.length();
ans=s;
}
}
cout<<ans<<endl;
getch();
}
Time Complexity: O(n2)
Space Complexity: O(1)
is there is any error in my solution ?
Dude,
there are many silly mistakes in your code, first correct them .
can u plz tell me case for which it is giving wrong answer