最長迴文子串模板

這裏先提前注意一下,子串和子序列是兩個不同的東西:

  • 子串:連續的子字符串/數組
  • 子序列:可以不連續(可間斷)的子字符串/數組

迴文串是面試常常遇到的問題(雖然問題本身沒啥意義),本文就告訴你迴文串問題的核心思想是什麼。

首先,明確一下什:迴文串就是正着讀和反着讀都一樣的字符串

比如說字符串abaabba都是迴文串,因爲它們對稱,反過來還是和本身一樣。反之,字符串abac就不是迴文串。

可以看到迴文串的的長度可能是奇數,也可能是偶數,這就添加了迴文串問題的難度,解決該類問題的核心是雙指針。下面就通過一道最長迴文子串的問題來具體理解一下回文串問題:

下面,就來說一下如何使用雙指針。

尋找回文串的問題核心思想是:從中間開始向兩邊擴散來判斷迴文串。對於最長迴文子串,就是這個意思:

for 0 <= i < len(s):
    找到以 s[i] 爲中心的迴文串
    更新答案

但是呢,我們剛纔也說了,迴文串的長度可能是奇數也可能是偶數,如果是abba這種情況,沒有一箇中心字符,上面的算法就沒轍了。所以我們可以修改一下:

for 0 <= i < len(s):
    找到以 s[i] 爲中心的迴文串
    找到以 s[i] 和 s[i+1] 爲中心的迴文串
    更新答案
代碼實現
string palindrome(string &s, int left, int right){
    // 防止索引越界
    while(left >= 0 && right < s.size() && s[left] == s[right]){
        // 向兩邊展開
        left--;
        right++;
    }
    // 返回以s[left]和s[right]爲中心的最長迴文串
    return s.substr(left + 1, right - left - 1);
}

string longestPalindrome(string s){
    if(s.size() < 2)
        return s;
    int length = s.size();
    string ans;
    for(int i = 0; i < length; i++){
        // 以s[i]爲中心的最長迴文子串
        string s1 = palindrome(s, i, i);
        // 以s[i],s[i+1]爲中心的最長迴文子串
        string s2 = palindrome(s, i, i + 1);
        ans = ans.size() > s1.size() ? ans : s1;
        ans = ans.size() > s2.size() ? ans : s2;
    }
    return ans;
}

至此,這道最長迴文子串的問題就解決了,時間複雜度 O(N^2),空間複雜度 O(1)。

值得一提的是,這個問題可以用動態規劃方法解決,時間複雜度一樣,但是空間複雜度至少要 O(N^2) 來存儲 DP table。這道題是少有的動態規劃非最優解法的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章