一、Problem
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
輸入:"aacdefcaa"
預期:"aa"
二、Solution
方法一:暴力
- 不用先取子串,可以利用 s 的字符串數組根據索引進行全局比較
- 取子串的話會超時的。
class Solution {
char[] cs;
public String longestPalindrome(String s) {
if (s.length() == 1)
return s;
String res = "";
cs = s.toCharArray();
int max = 0;
for (int i = 0; i < s.length(); i++)
for (int j = i; j < s.length(); j++) {
if (is(i, j) && j-i+1 > max) {
res = s.substring(i, j+1);
max = j-i+1;
}
}
return res;
}
boolean is(int l, int r) {
while (l < r) {
if (cs[l] != cs[r])
return false;
l++; r--;
}
return true;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:轉化爲 LMS 問題
從迴文串的性質出發,將問題轉化爲求解最長公共子串問題:
- 定義狀態:
- 表示以 開始和以 結束的迴文子串的長度。
- 思考初始化:
- 單個字符 LMS 長度爲 1
- 思考狀態轉移方程:
- 如果 ,可推出
- 否則,
- 思考輸出:
還是 99 / 103 WA 了?這確實打臉…
"aacdefcaa"
輸出:"aac"
預期:"aa"
class Solution {
public String longestPalindrome(String s) {
char s1[] = s.toCharArray(), s2[] = new StringBuilder(s).reverse().toString().toCharArray();
int max = 0, e = 0, n = s1.length, dp[][] = new int[n+1][n+1];
for (int i = 1; i <= n; i++)
dp[i][i] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
if (s1[i-1] == s2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
if (dp[i][j] > max) {
max = dp[i][j];
e = i;
}
} else dp[i][j] = 0;
}
return s.substring(e-max, e);
}
}
方法三:dp
- 定義狀態:
- 的真值表示子串 是否爲迴文子串
- 思考初始化:
- 思考狀態轉移方程:
- 如果 ,此時會有兩種情況出現:
- 如果 中間沒有字符,那麼
- 如果 中間存在字符,那麼
- 如果 ,此時會有兩種情況出現:
class Solution {
public String longestPalindrome(String S) {
char[] s = S.toCharArray();
int max = 0, s = 0, n = s.length;
boolean[][] dp = new boolean[n][n];
for (int r = 0; r < n; r++)
for (int l = 0; l <= r; l++) {
if (s[l] == s[r] && (r - l < 2 || dp[l+1][r-1])) {
dp[l][r] = true;
if (r - l + 1 > max){
max = r-l+1;
s = l;
}
}
}
return S.substring(s, s+max);
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
還有啥中心擴展,代辦把