One of the solution for finding the longest palindromic substring could not be understood
I am stuck there, so I google to reach here. Now I understand.Let me take original String which the author mentioned as a example.
S = "caba', S' = "abac", so longest common substring is aba.
The sentence is "we check if the substring’s indices are the same as the reversed substring’s original indices."
1.What is the substring’s indices?
"aba" is [1, 2, 3]
2.what is reversed substring’s original indices? Reversed substring is "aba", and its original indices is also [1, 2, 3].
So that answer is correct.
And we are looking at another example.
S="abacdfgdcaba", S' = "abacdgfdcaba", so longest common substring is "abacd".
So same process:
1.What is the substring’s indices?
"abacd" is [0, 1, 2, 3, 4].
2.what is reversed substring’s original indices?
Reversed substring is "abacd"
, but its original indices is also [7, 8, 9, 10, 11]
.
So These two "abacd"
is not same one, the answer is not correct.
I think that sentence is a bit tricky, and I think the author made it a little hard to understand.
I think the sentence should be changed to "To rectify this, each time we find a longest common substring candidate, we check if the substring are the same one as the reversed substring’."
There are efficient algorithms for computing the longest palindromic substring by reversing the original substring. For example, the following:
1) create a generalized string S1#S2$ which takes O(n)
1) construct a suffix array O(n) -> not trivial, but there are easy O(nlogn) and O(nlog^2n) algorithms
2) construct an lcp array O(n) -> trivial (there is also a trivial O(nlogn) one).
3) construct an RMQ data structure: O(n) construction and O(1) querying -> not trivial (there are trivial O(nlogn) construction and O(logn) query ones)
4) Iterate over every position i in the original string S1. Find the complement position in S2 in the generalized string. Find the longest common prefix: O(1)
In general, the mentioned approach must be modified for even and odd length palindromes. The distinction is that in the odd length palindrome you just introduce a gap when selecting the indices.
This yields an O(n) solution to the problem.
Regarding the article:
The author mentions that finding the longest common substring is not enough since the two substrings with such lcp may not be neighbours in the original string.
Therefore, we want to find two strings A and B, one belonging to S1 and one to S2, such that lcp(A,B) is largest, but also A . rev(B) is in the original S1.
I hope I have been clear enough.
In case someone is looking for an implementation of the this question, where we use Longest Common Substring to find the Longest Palindromic Substring, this is my version of it.
package leetcodeproblems;
/**
* Created by Nandan Mankad on 23-11-19.
*/
public class LongestPalindromicSubstring {
public static void main(String[] args) {
/*String s = "aacdefcaa";*/
/*String s = "dabcbae";*/
/*String s = "babad";*/
/*String s = "cbbd";*/
/*String s = "cbbc";*/
String s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
System.out.println(longestPalindrome(s));
}
public static String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return s;
}
StringBuilder sb = new StringBuilder(s);
String revString = sb.reverse().toString(); // Reversing the string - to compute LCS.
int dp[][] = new int[s.length() + 1][s.length() + 1];
int maxLength = 0;
int iPos = 0;
for (int i = 1; i < dp.length; i++) {
for (int j = 1; j < dp.length; j++) {
if (s.charAt(i - 1) == revString.charAt(j - 1)) { // Character matches in Original String and Reversed String.
dp[i][j] = dp[i - 1][j - 1] + 1; // Standard Longest Common Substring logic for Original and Reversed String.
int revIdx = i;
int forIdx = j - dp[i][j] + 1;
if (s.length() - revIdx + 1 == forIdx) { // Here we check if the reverse string original idx is same as original string idx.
if (maxLength < dp[i][j]) {
maxLength = dp[i][j];
iPos = i;
}
}
} else {
dp[i][j] = 0;
}
}
}
StringBuilder res = new StringBuilder();
while (maxLength > 0) {
res.append(s.charAt(iPos- 1));
maxLength--;
iPos--;
}
return res.toString();
}
}
Link
It passes all the testcases on Leetcode for the problem. Improvisations might be possible where we iterate the string in reverse and not reverse the actual string, etc.
Time Complexity: O(N^2) Space Complexity: O(N^2)