中心擴散法解決迴文串問題
阿新 • • 發佈:2020-12-31
技術標籤:字串
迴文串
概述
找一個序列的最長迴文串方法有很多,暴力求解,dp,中心擴散,還有Manacher(馬拉車)等,中心擴散的時間複雜度O(n^2),而且相比於dp,不需要開闢額外的空間,實際操作上比dp稍微高效一點。又比較容易理解。
一般的方法
如果是判斷是否為迴文串,我們一般這樣做
public boolean valid(char[] str, int l, int r){
while (l < r){
if (str[l++] != str[r--]) {
return false;
}
}
return true;
}
中心擴散
中心擴散則是選取中點,向兩邊擴散,以確定迴文串最大長度的方法。要注意中心是一個還是兩個的情況,即對字串長度奇偶性的討論。
leetcode5
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。
用中心擴散法,返回最大長度,我們可以通過選取的中點倒推出字串的起點。
public class Solution {
public String longestPalindrome(String s) {
int len = s.length();
char[] str = s.toCharArray();
int begin = 0, end = 0;
for (int i = 0; i < len; i++) {
int len1 = expand(str, i, i);
int len2 = expand(str, i, i + 1);
int max_len = Math.max(len1, len2);
if (max_len > end - begin){
begin = i - (max_len - 1) / 2;
end = i + max_len / 2;
}
}
return s.substring(begin, end + 1);
}
public int expand(char[] s, int l, int r){
while (l >= 0 && r < s.length && s[l] == s[r]){
l--;
r++;
}
//注意這裡s[l] != s[r],返回的長度應當注意
return r - l - 1;
}
}
leetcode647
給定一個字串,你的任務是計算這個字串中有多少個迴文子串。
具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被視作不同的子串。
稍作改動,我們遍可以解決這個問題了,因為中心擴散法實際上相當於遍歷了所有的迴文串,我們只需要多引入一個計數器即可
class Solution {
int res = 0;
public int countSubstrings(String s) {
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; ++i){
expand(chars, i, i);
expand(chars, i, i + 1);
}
return res;
}
public void expand(char[] s, int l, int r){
while(l >= 0 && r < s.length){
if(s[l--] != s[r++]){
break;
}
res++;
}
}
}