給出乙個字串s,求s的最長回文子串的長度。
樣例:字串「patzjujztaccbcc」的回文子串為「atzjujzta」,長度為9。
如果使用暴力解法,列舉子串的兩個端點i和j,時間複雜度需要o(n^2)。判斷子串是否為回文需要o(n),總體時間複雜度為o(n^3),使用動態規劃可以達到最優的o(n^2),而使用動態規劃解決最長回文子串的方法有很多種,下面討論最簡單的一種方法。
令dp[i][j]表示s[i]至s[j]所表示的子串是否為回文子串,是則為1,不是為0。如此根據s[i]是否等於s[j],可以把問題分為兩類:
(1)s[i]==s[j],那麼只要s[i+1]至s[j-1]是回文子串,s[i]至s[j]就是回文子串;如果s[i+1]至s[j-1]是不是回文子串,則s[i]至s[j]也不是回文子串。
(2)s[i]!=s[j],那麼s[i]至s[j]一定不是回文子串。
由此可以 寫出其狀態轉移方程:
邊界:dp[i][i]=1,dp[i][i+1]=(s[i]==s[i+1]?0:1) ps:這裡的dp初始化記錄了長度為1和2的回文子串
但是這裡還存在乙個問題,就是在求dp[i][j]時,無法保證dp[i+1][j-1]已經被計算了,比如先固定i=0,然後j從2開始列舉。當求解dp[0][2]時,的dp[1][1]已經在初始中得到;當求解dp[0][3]時,會轉換求dp[1][2],而dp[1][2]也在初始化是獲得了;當求解dp[0][4]是,轉換求解dp[1][3],但dp[1][3]之前卻沒有被計算出來,因此無法轉移狀態。
根據上面的公式,邊界表示的是長度為1和2的回文子串,且每次轉移時都說對子串的長度減1。因此不妨按照子串的長度和子串的初始位置進行列舉,即第一次可以列舉長度為3的子串的dp值,第二次在第一次的基礎上列舉長度為4的子串的dp值....直到列舉到原字串的長度。長度為3的示意圖如下:
根據上面的分析,可以給出下面的**:
#include #include #include using namespace std;
const int m=1010;
int dp[m][m];
int main()
bool isdigit(char c)
char* toupper(char* v)
} return v;
}int main()
} str=toupper(str);
int len=strlen(str);
for(i=0;i=0;j--)
} }
s=pos[s]; e=pos[e];
for(i=s;i<=e;i++)
printf("\n");
}
另外關於o(n)的回文演算法manacher,可以參考: 力扣演算法篇 最長回文子串
求解len i 設 l,r 表示當前最靠右的子回文串的邊界 1 若i r,則該子回文串對len i 的計算無法起到任何幫助,直接呼叫樸素演算法計算len i 2 若i r,則說明元素s i 處於該子回文串內,由於回文串的特性,我們可以在該子回文串的左側找到乙個與s i 對稱的元素s j 那麼我們可以...
演算法 最長回文子串
題目描述 對於乙個字串,請設計乙個高效演算法,計算其中最長回文子串的長度。給定字串a以及它的長度n,請返回最長回文子串的長度。例如 輸入 abc1234321ab 12 返回值 7 最長回文子串 public static intgetlongestpalindrome string a,int n...
最長回文串 演算法 4 求解最長回文子串
問題描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。注釋 回文通俗的說就是正著念和反著念都一樣,如 上海自來水來自海上。示例 1 輸入 dabccbac 輸出 abccba 示例 2 輸入 cbbd 輸出 bb 解題思路 此處撰寫解題思路 遍歷每乙個索引,...