最長の回文部分文字列
問題の説明
文字列sを指定し、sで最長の回文部分文字列を見つけます。
問題解決のアイデア
以前のこの質問と同様の質問:最長の回文サブシーケンス。
違いは、質問が最長の回文サブシーケンスの長さを返すのに対し、この質問は最長の回文サブストリングを返すことです。つまり、戻り値は文字列型です。
戻り値は異なりますが、要件は同じであるため、動的計画法を使用してこの問題を解決することもできます:
部分文字列の場合、それが回文であり、長さが2より大きい場合、最初と最後の2文字を削除した後でも、それは回文のままです。dp(i、j)を使用して、文字列sのi番目の文字で構成される文字列が回文であるかどうかを示します。s[i、j]が回文である場合、s [i] == s [j] 、および両端を削除した後の部分文字列は、まだ回文です。したがって、状態遷移方程式を記述します。
dp(i、j)==(s [i-1] == s [j + 1])&& dp(i + 1、j-1)
次に、最長の回文部分文字列は、dp [i] [j]が真であり、j-i +1が最長の文字列です。
コード:
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
String res = "";
for (int l = 0; l < n; ++l) {
//l表示回文串的长度-1
for (int i = 0; i + l < n; ++i) {
//i为子串起点
int j = i + l;//j为子串终点
if (l == 0) {
//此为 i == j 的情况
dp[i][j] = true;
} else if (l == 1) {
//此为回文串只有两个字符的情况,需要两个字符相等才能为真
dp[i][j] = (s.charAt(i) == s.charAt(j));
} else {
//推导出的状态转移方程
dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]);
}
if (dp[i][j] && l + 1 > res.length()) {
//求最长串
res = s.substring(i, i + l + 1);
}
}
}
return res;
}
}
時間計算量:O(n ^ 2)
空間計算量:O(n ^ 2)
解決策2:
このソリューションは、文字列の各文字をトラバースし、それを回文の中心として使用するという考え方も提供します。中心が左側と右側に等しい場合は、拡大を続けます。等しくない場合は、トラバースを続けます。次のキャラクター。
イラスト:出典
コード:
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
public int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return right - left - 1;
}
}
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)