1. 程式人生 > 其它 >中心擴散法解決迴文串問題

中心擴散法解決迴文串問題

技術標籤:字串

迴文串

概述

找一個序列的最長迴文串方法有很多,暴力求解,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++;
        }
    }
}