我已经解决了寻找最长回文子串的问题,但这是不同的。 给定一个像“ababa”这样的字符串,all前缀的最长回文子串的长度将如下 -
这是示例输入/输出 ->
我想了几个解决方案 -
我们只需要长度,而不需要实际的回文。有没有我错过的更简单/更好(就运行时复杂性而言)的方法?
更新:我们需要字符串所有前缀的长度(最长回文子串)(如上面的示例所示)。
第二个选项。想想manacher是如何工作的。每次移动右指针时,它基本上都会考虑一个新的前缀。在每次迭代中跟踪管理器表值的当前计算部分中的最大值,即当前前缀的最长回文子序列的长度(在右侧指针处结束)。这需要 O(n) 时间。
我建议这个解决方案:https://www.geeksforgeeks.org/longest-palindromic-substring-set-2/?ref=rp,它的时间复杂度是 O(N^2) ,空间复杂度是 O( 1)。 但在你的情况下,你需要一个数组(maxArr)来保存前缀的最大长度子字符串的长度
想法保持不变,你选择一个中心并以此为中心找到最大长度的子串。在最大子字符串结束的地方,更新该位置的数组中的最大长度。 最后,数组中可能有一些位置为空(maxArr),这些位置将与它们的左侧位置保持相同的值。
这是一个解决方案:
public static int[] solve(String S) {
int n = S.length();
boolean[][] palindromeDP = new boolean[n][n];
int[][] lengthDP = new int[n][n];
for(int i=0;i<n;i++) {
// single letter are palindrome
palindromeDP[i][i] = true;
lengthDP[i][i] = 1;
}
for(int i=1;i<n;i++) {
// two letter palindrome (i and i-1)
if(S.charAt(i-1) == S.charAt(i)) {
palindromeDP[i-1][i] = true;
lengthDP[i-1][i] = 2;
} else {
palindromeDP[i-1][i] = false;
lengthDP[i-1][i] = 1;
}
}
for(int i=2;i<n;i++) {
for(int j=0; j<n-i;j++) {
// string[j:i]
if(palindromeDP[j + 1][j + i - 1] && (S.charAt(j+i) == S.charAt(j))) {
// middle is palindrome and side letter are equal, it's a palindrome
// add two more in length of the new side letters
palindromeDP[j][j+i] = true;
lengthDP[j][j+i] = lengthDP[j + 1][j + i - 1] + 2;
} else {
// remains same till now
palindromeDP[j][j+i] = false;
lengthDP[j][j+i] = lengthDP[j + 1][j + i - 1];
}
}
}
int[] result = new int[n];
int maxTillNow = 1;
for(int i=0;i<n;i++) {
if(maxTillNow < lengthDP[0][i]) {
maxTillNow = lengthDP[0][i];
}
result[i] = maxTillNow;
}
return result;
}
package code.shubham;
import java.util.Arrays;
public class LongestPalindromicSubstringForEachPrefix {
class Solution {
int[] solve(String s) {
int[] dp = new int[s.length()];
lps(s, dp);
for (int i = 1; i < s.length(); i++)
dp[i] = Math.max(dp[i], dp[i-1]);
return dp;
}
void lps(String s, int[] dp) {
for (int i = 0; i < s.length(); i++) {
expand(s, i, i, dp);
expand(s, i, i + 1, dp);
}
}
int expand(String s, int l , int r, int[] dp) {
while (l > -1 && r < s.length() && s.charAt(l) == s.charAt(r)) {
l--;
r++;
}
l++;
r--;
dp[r] = Math.max(dp[r], r - l + 1);
return r - l + 1;
}
}
public static void main(String[] args) {
Arrays.stream(
new LongestPalindromicSubstringForEachPrefix(). new Solution().solve("abaaabbbaa")
).forEach(e -> System.out.print(e + " "));
}
}