LeetCode/最長迴文子串
阿新 • • 發佈:2022-05-09
描述
對於長度為n的一個字串A(僅包含數字,大小寫英文字母),請設計一個高效演算法,計算其中最長迴文子串的長度。
思路
1.暴力列舉所有串,判斷串是否為迴文串並將當下最長的進行儲存
2.中心擴散,順序遍歷,對每個點進行左右同時擴散,得到其中心點對應的最大回文串和迴文串長度(考慮奇偶串要分別用一箇中心和兩個中心點進行遍歷),時間複雜度為O(n2),空間複雜度為O(1)
3.動態規劃,用二維dp陣列記錄任意兩點間是否為迴文串
狀態轉移方程:dp[i][j]=(s[i]==s[j])and dp[i+1][j-1]
邊界條件:j-i<3(即字串長度為2和3時不用再檢查子串)
合理的遞推順序(小串到大串)即能把任意兩點是否為迴文串計算出來
時間複雜度為O(n2),空間複雜度為O(n2)
4.Manacher演算法,中心擴散的時候可以結合動態規劃的思想,將已經擴散計算過的點進行儲存,使得演算法效能成為線性
中心擴散C++
點選檢視程式碼
class Solution { public: string longestPalindrome(string s) { int maxlen = 1;//單字元進不了迴圈預設為1 int begin,single,doubles; begin = 0; for(int i=0;i<s.length()-1;i++){ single = fun(s,i,i);//奇串 doubles = fun(s,i,i+1);//偶串 //記錄最長字串對應起始位置 if(single>maxlen&&single>doubles){ maxlen = single; begin = i-maxlen/2; } else if(doubles>maxlen){ maxlen = doubles; begin = i-maxlen/2+1; } } return string(s,begin,maxlen); } //fun函式返回指定中心點的迴文串長度 int fun(string &s,int begin,int end){ while(begin>=0 && end<s.length() &&s[begin]==s[end]){ begin--; end++; } return end-begin-1; } };
動態規劃C++
點選檢視程式碼
class Solution { public: string longestPalindrome(string s) { int n = s.size(); if (n < 2) { return s; } int maxLen = 1; int begin = 0; // dp[i][j] 表示 s[i..j] 是否是迴文串 vector<vector<int>> dp(n, vector<int>(n)); // 初始化:所有長度為 1 的子串都是迴文串 for (int i = 0; i < n; i++) { dp[i][i] = true; } // 遞推開始 // 先列舉子串長度 for (int L = 2; L <= n; L++) { // 列舉左邊界,左邊界的上限設定可以寬鬆一些 for (int i = 0; i < n; i++) { // 由 L 和 i 可以確定右邊界,即 j - i + 1 = L 得 int j = L + i - 1; // 如果右邊界越界,就可以退出當前迴圈 if (j >= n) { break; } if (s[i] != s[j]) { dp[i][j] = false; } else { if (j - i < 3) { dp[i][j] = true; } else { dp[i][j] = dp[i + 1][j - 1]; } } // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是迴文,此時記錄迴文長度和起始位置 if (dp[i][j] && j - i + 1 > maxLen) { maxLen = j - i + 1; begin = i; } } } return s.substr(begin, maxLen); } };