資料結構演算法題/最長迴文子串
阿新 • • 發佈:2018-11-19
迴文表示字串正向和反向是相同的。例如a, aba, abccba
一、暴力法
最容易想到的就是暴力破解,求出每一個子串,之後判斷是不是迴文,找到最長的那個。
求每一個子串時間複雜度O(N^2), 判斷子串是不是迴文O(N),兩者是相乘關係,所以時間複雜度為O(N^3)。
二、動態規劃
下面介紹動態規劃的方法,使用動態規劃可以達到最優的 O(n2) 複雜度。
令 dp[i][j] 表示 S[i] 至 S[j] 所表示的子串是否是迴文子串,是則為 1,不是則為 0。這樣根據 S[i] 是否等於 S[j] ,可以把轉移情況分為兩類:
- 若 S[i] == S[j],那麼只要 S[i+1] 至 S[j-1] 是迴文子串,S[i] 至 S[j] 就是迴文子串;如果S[i+1] 至 S[j-1] 不是迴文子串,則 S[i] 至 S[j] 也不是迴文子串。
- 若 S[i] != S[j],那麼 S[i] 至 S[j] 一定不是迴文子串。
根據遞推寫法從邊界出發的原理,注意到邊界表示的是長度為 1 和 2 的子串,且每次轉移時都對子串的長度減了 1,因此不妨考慮按子串的長度和子串的初始位置進行列舉,即第一遍將長度為 3 的子串的 dp 值全部求出,第二遍通過第一遍結果計算出長度為 4 的子串的 dp 值
public class LongestPalindromicSubstring { public String longestPalindrome(String s) { int n = s.length(); boolean dp[][] = new boolean[n][n]; int maxlen = 1; //儲存最長迴文子串長度 int start = 0; //儲存最長迴文子串起點 for(int i = 0; i < n; ++i) { for(int j = 0; j <= i; ++j) { if(i - j < 2)//包含了i=j和i-j=1的情況 { dp[j][i] = (s.charAt(i) == s.charAt(j)); } else { dp[j][i] = (s.charAt(i) == s.charAt(j) && dp[j + 1][i - 1]); } if(dp[j][i] && maxlen <= i - j + 1)//j到i之間的子串是迴文子串 { maxlen = i - j + 1; start = j; } } } return s.substring(start, start + maxlen); } public static void main(String[] args) { LongestPalindromicSubstring longestPalindromicSubstring = new LongestPalindromicSubstring(); System.out.println(longestPalindromicSubstring.longestPalindrome("QATZJUJZTA")); } }
三、中心擴充套件法
中心擴充套件就是把給定的字串的每一個字母當做中心,向兩邊擴充套件,這樣來找最長的子迴文串。演算法複雜度為O(N^2)。
需要考慮兩種情況:
長度為奇數的迴文串,比如a, aba, abcba
長度為偶數的迴文串,比如aa, abba
public String longestPalindrome2(String s)
{
int len = s.length();
int maxlen = 1;
int start = 0;
for(int i = 0; i < len; i++)//求長度為奇數的迴文串
{
int j = i - 1, k = i + 1;//j和k分別是i的兩邊
while(j >= 0 && k < len && s.charAt(j) == s.charAt(k))
{
if(k - j + 1 > maxlen)
{
maxlen = k - j + 1;
start = j;
}
j--;
k++;
}
}
for(int i = 0; i < len; i++)//求長度為偶數的迴文串
{
int j = i, k = i + 1;//奇數和偶數的區別在於j的初始值
while(j >= 0 && k < len && s.charAt(j) == s.charAt(k))
{
if(k - j + 1 > maxlen)
{
maxlen = k - j + 1;
start = j;
}
j--;
k++;
}
}
return s.substring(start, start + maxlen);
}
四、Manacher演算法
Manacher演算法的時間複雜度為O(N),具體可參考:
https://blog.csdn.net/qq_32354501/article/details/80084325
https://www.cnblogs.com/grandyang/p/4475985.html
https://www.jianshu.com/p/c82cada7e5b0
https://www.cnblogs.com/coderJiebao/p/Algorithmofnotes30.html