求最長迴文子串(多種解法)
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
解析:
1.暴力解法,時間複雜度O(n^3),此種方法時間超出,未能AC。
2.動態規劃解法string longestPalindrome(string s) { int i, j, len = s.length(); int maxn=0,cnt = 0; string res=""; for (i = 0; i<len; ++i){ for (j = i; j<len; ++j){ for (int k = 0; j - k >= 0 && i + k <= len&&i + k <= j - k; ++k){ if (s[i + k] == s[j - k]){ cnt++; } else{ break; } } if (((j - i + 1) % 2==0 && cnt == (j - i + 1) / 2)||((j-i+1)%2==1&&(cnt==(j-i+1)/2+1))){ if (j - i >= maxn){ maxn = j - i; res = s.substr(i, j - i + 1); } } cnt = 0; } } return res; }
假設dp[i][j]的值為true,表示字串s中下標從i到j的字元組成的子串是迴文串。那麼可以推出:
dp[i][j]=dp[i+1][j-1]&&s[i]==s[j]
這是一般的情況,由於需要依靠i+1,j-1,所以有可能i+1=j-1,i+1=(j-1)-1,因此需要求出基準情況才能套用以上公式。
a. i+1 = j-1 ,即迴文長度為1時,dp[i][i]=true;
b. i+1 = (j-1)-1,即迴文長度為2時,dp[i][i+1]=(s[i]==s[i+1])。
此種方法 記憶體超出,未能AC。string longestPalindrome02(string s){ int n = s.length(); bool **dp = new bool*[n]; for (int i = 0; i < n; ++i){ dp[i] = new bool[n]; } //基準情況 int start = 0; int max = 1; for (int i = 0; i < n; ++i){ dp[i][i] = true; if (i + 1 < n){ if (s[i] == s[i + 1]){ dp[i][i + 1] = true; start = i; max = 2; } else dp[i][i + 1] = false; } } //動態規劃求解,前面已經求解了len = 1 ,len = 2的情況了 for (int len = 3; len <= n; ++len){ for (int i = 0; i < n - len + 1; ++i){ int j = i + len - 1; if (dp[i+1][j-1]&&s[i]==s[j]){ dp[i][j] = true; int curLen = j - i + 1; if (curLen>max){ start = i; max = curLen; } } else dp[i][j] = false; } } for (int i = 0; i < n; ++i){ delete[] dp[i]; delete[] dp; return s.substr(start,max); } }
3.中心擴充套件法
因為迴文字串是以中心軸對稱的,所以如果我們從下標i出發,用2個指標向i的兩邊擴充套件判斷是否相等,那麼只需要對0到n-1的下標都做此操作,就可以求出最長的迴文子串。
但需要注意的是,迴文字串有奇偶對稱之分,即“abcba”和“abba”2種類型。
因此需要在程式碼中做出判斷。
設int Palindromic(string &s,int i,int j)是求下標i和j向兩邊擴充套件的迴文串的長度,那麼對0至n-1的下標,呼叫兩次此函式:
int lenOdd = Palindromic(str,i,i)和int lenEven = Palindromic(str,i,j),即可求得以i下標為奇迴文和偶迴文的子串長度。
接下來以lenOdd和lenEven中的最大值與當前最大值max比較即可。
這個方法有一個好處是時間複雜度為O(n^2),且不需要使用額外的空間。
class Solution {
public:
string longestPalindrome(string s){
int n = s.length();
int start = 0;
int maxn = 1;
for (int i = 0; i < n; ++i){
int oddLen = 0, evenLen = 0, curLen;
oddLen = Palindromic(s, i, i);
if (i + 1 < n){
evenLen = Palindromic(s, i, i + 1);
}
curLen = oddLen > evenLen ? oddLen : evenLen;
if (curLen>maxn){
maxn = curLen;
if (maxn & 0x1){
start = i - maxn / 2;
}
else{
start = i - (maxn - 1) / 2;
}
}
}
return s.substr(start, maxn);
}
public:
int Palindromic(string &str,int i,int j){
int n = str.length();
int curLen = 0;
while (i >= 0 && j < n&&str[i] == str[j]){
--i; ++j;
}
curLen = (j - 1) - (i + 1) + 1;
return curLen;
}
};
46ms,AC
第四種解法:Manacher演算法的O(n)的演算法,下次更新