方法一:中心擴展算法算法
解題思路:從左到右每個字符都做爲中心軸,而後逐漸往兩邊擴展,只要發現有不相等的字符,則肯定了以該字符爲軸的最長迴文串,但須要考慮長度爲奇數和偶數的不一樣狀況的處理(長度爲偶數時軸心爲中間兩個數的中心,長度爲奇數時軸心爲中間那個數)spa
算法時間複雜度:$O(n^{2})$code
string longestPalindrome(string s) { int idx = 0, maxL = 0; for (int i = 0; i < s.size(); ++i) // i爲軸的位置,j爲迴文串半徑 { for (int j = 0; i - j >= 0 && i + j < s.size(); ++j) // 奇數 { if (s[i - j] != s[i + j]) break; if (2 * j + 1 > maxL) { maxL = 2 * j + 1; idx = i - j; } } for (int j = 0; i - j >= 0 && i + j + 1 < s.size(); ++j) // 偶數 { if (s[i-j]!=s[i+j+1]) break; if (2 * j + 2 > maxL) { maxL = 2 * j + 2; idx = i - j; } } } return s.substr(idx, maxL); }
方法二:manacher(馬拉車法)blog
解題思路:詳見P3805 【模板】manacher算法get
算法時間複雜度爲:$O(n)$string
int pos[2005],p[2005]; string longestPalindrome(string s) { /* 填充字符,統一爲奇數串 */ string s_new="~"; for (int i=0,k=1;i<s.size();++i) { s_new+="#"; s_new+=s[i]; pos[k++]=i; // 記錄新字串與原始字串的位置關係 pos[k++]=i; } s_new+="#"; /* manacher */ int m=0,r=0,maxL=0,idx=0; for (int i=1;i<s_new.size();++i) { // 獲取已知的最小回文半徑 if (i<r) p[i]=min(p[2*m-i],r-i); else p[i]=1; // 暴力拓展左右兩側 while (s_new[i-p[i]]==s_new[i+p[i]]) p[i]++; // 新的迴文半徑比較大,則更新 if (r-i<p[i]) { m=i; r=i+p[i]; } // 更新迴文長度(原始字串的迴文長度爲新字串迴文半徑-1) if (p[i]-1>maxL) { maxL=p[i]-1; idx=pos[i]-maxL/2; // 更新原始迴文字串的起始位置 } } return s.substr(idx,maxL); }