求最長迴文子串

迴文串,就是指正讀和反讀都一樣的字符串,比如"level"或者"noon"等等。

那麼,如何求一個字符串的最長迴文子串(Longest Palindromic Substring)?這裏我們有多種解法。

解法一:暴力法

暴力解法就是直接枚舉所有子串,對每個子串判斷是否爲迴文,時間複雜度爲O(n3)

這是最糟糕的方法,相信面試官問你這個問題,絕對不是想要這個答案。

解法二:動態規劃法O(n2)

動態規劃法是在暴力解法上進行的優化。通過記錄一些我們需要的東西,來避免暴力解法中很多重複的判斷。

假設 dp[i][j] 表示子串 s[i...j] 是否是迴文,那麼對於動態規劃表 dp 的打表方式如下:

  • 初始化:

    dp[i][i]=truedp[i][i1]=trueothers=fasle(0 <= i <= n-1)(1 <= i <= n-1) 
  • 動態規劃的狀態轉移方程:

    dp[i][j]=dp[i+1][j1],false,if s[i] == s[j]if s[i] ≠ s[j]

C++代碼如下

string longestPalindrome(string s) {
    int len = s.size();
    if(len <= 1) return s;
    // 動態規劃表,全部初始化爲true
    vector<vector<bool>> dp(len, vector<bool>(len, true));

    int start = 0, maxlen = 0;
    for(int k=2; k<=len; ++k) {    // 枚舉子串的長度
        for(int i=0; i<=len-k; ++i) {  // 枚舉子串起始位置
            int j = i+k-1;
            if(s[i] == s[j] && dp[i+1][j-1])
            {
                dp[i][j] = true;
                start = i;      // 記錄迴文子串的起點和長度
                maxlen = k;
            }
        }
    }

    return s.substr(start, maxlen);
}

解法三:中心擴展法O(n2)

這個算法思想其實很簡單,就是對給定的字符串S,分別以該字符串S中的每一個字符 c 爲中心,向兩邊擴展,記錄下以字符 c 爲中心的迴文子串的長度。時間複雜度爲O(n2) ,空間複雜度僅爲O(1)

但有一點需要注意的是,迴文的情況可能是 a b a,也可能是 a b b a。

// 分別向左右擴展,返回擴展後的字符串
string expand(string s, int left, int right) {
    int len = s.size();
    while (left>=0 && right<len && s[left] == s[right]) 
    {
        left--;
        right++;
    }
    return s.substr(left+1, right-left-1);
}

// 求最長迴文子串
string longestPalindrome(string s) {
    int len = s.size();
    if(len<=1) return s;

    string longest;
    for (int i=0; i<len-1; i++) 
    {
        string p1 = expand(s, i, i);  // 奇數
        if (p1.size() > longest.size())
            longest = p1;

        string p2 = expand(s, i, i+1);  // 偶數
        if (p2.size() > longest.size())
            longest = p2;
    }
    return longest;
}




另外,據說還有一個很巧妙的算法,叫Manacher算法,可以在 O(n) 的時間複雜度裏求出最長迴文子串。由於這個算法我沒有研究過,在這裏就不介紹了。







個人站點:http://songlee24.github.com

發佈了111 篇原創文章 · 獲贊 250 · 訪問量 82萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章