Longest Palindromic Substring
lintcode
Total Accepted: 99803 Total Submissions: 438290 Difficulty: Medium
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring
思路1
- 区间型动态规划O(n2)
- Manacher O(n)但是不用去刻意掌握
- 使用substring这个函数其实是O(n)时间复杂度,所以不要直接用,而是记录下Index就好了
public class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) {
return new String();
}
int size = s.length();
boolean[][] dp = new boolean[size][size];
String longest = new String();
int start = 0;
int end = size - 1;
for (int i = 0; i < size; i++) {
dp[i][i] = true;
}
for (int i = 0; i + 1< size; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
dp[i][i + 1] = true;
start = i;
end = i + 1;
}
}
for (int len = 2; len < size; len++) {
for (int i = 0; i + len < size; i++) {
if (s.charAt(i) == s.charAt(i + len) && dp[i + 1][i + len - 1]) {
dp[i][i + len] = true;
start = i;
end = i + len;
}
}
}
longest = s.substring(start, end + 1);
return longest;
}
}
思路2
- 基于中心点枚举的算法
- 输入"abcdzdcab", 在输入的每个字符和字符间隙放一个指针
- 第一种情况: a|b 或者 a|a 这是第一个空位,检查指针两边是否相等
- 第二种情况: abc, 指针在b上,检查a和c是否相等
- 注意substring不要写在循环里边,否则就是O(n3)时间复杂度
public class Solution {
public String longestPalindrome(String s) {
if (s == null || s.equals("")) {
return new String("");
}
if (s.length() == 1) {
return new String(s);
}
int max = 0;
int start = 0;
int end = s.length();
for (int i = 1; i <= s.length(); i++) {
for (int range = 1; i - range >= 0 && i + range - 1 < s.length(); range++) {
char c1 = s.charAt(i - range);
char c2 = s.charAt(i + range - 1);
if (c1 == c2) {
if (max < range * 2) {
max = range * 2;
start = i - range;
end = i + range - 1;
}
} else {
break;
}
}
for (int range = 1; i - range >= 0 && i + range < s.length(); range++) {
char c1 = s.charAt(i - range);
char c2 = s.charAt(i + range);
if (c1 == c2) {
if (max < range * 2 + 1) {
max = range * 2 + 1;
start = i - range;
end = i + range;
}
} else {
break;
}
}
}
return s.substring(start, end + 1);
}
}
思路3
- 基于中心点枚举的算法
- 只不过用了两次循环,没有必要真的加入虚拟index,那样容易弄乱
public class Solution {
public String longestPalindrome(String s) {
if (s.equals("")) {
return new String("");
}
int longestLength = 0;
int start = 0;
int end = s.length() - 1;
for (int i = 0; i < s.length(); i++) {
int j = 0;
while (i - j >= 0 && i + j < s.length() && s.charAt(i - j) == s.charAt(i + j)) {
if (longestLength < 2 * j + 1) {
longestLength = 2 * j + 1;
start = i - j;
end = i + j;
}
j++;
}
j = 0;
while (i - j - 1 >= 0 && i + j < s.length() && s.charAt(i - j - 1) == s.charAt(i + j)) {
if (longestLength < 2 * j + 2) {
longestLength = 2 * j + 2;
start = i - j - 1;
end = i + j;
}
j++;
}
}
System.out.println(start);
System.out.println(end + 1);
return s.substring(start, end + 1);
}
}