题目
My way
状态定义:
\[ \begin{align*} & s:\ 字符串s\\ & i:\ 字符串s第i位\\ & j:\ 字符串s第j位\\ & s[i:j]:\ 字符串s第i位到第j位的子串, s[i,j]\\ & dp[i][j]:\ dp数组在s[i,j]上是否为回文串的记录。 \end{align*} \]
Base case:
\[ \begin{align*} &s[i][j] = 1, &\text{if $i==j$}\ \end{align*} \]
状态转移方程:
\[ s[i-1][j+1] = \begin{cases} & 1,\ \text{if $s[i] == s[j]$}\\ & 0,\ otherwise \end{cases} \]
Error:
在如何实现数组遍历上面,出现了问题。
套用了 glamour的逆向对角遍历思路:
1 | class Solution { |
Glamour way
1.DP + 逆向对角遍历
逆向对角遍历思路:
上图中同一条直线上的值有前者依赖于后者的关系,因此我们应该以对角线方向遍历
但是本方法在發現一字符串不是回文串后,仍然對包含其的字符串進行回文判斷。
此方法包含了冗餘的判斷,因此還有優化的地方。
1 | public int countSubstrings(String s) { |
2. 分治法 + 中心扩散法
分治法,对以不同字符为中心的回文分而治之,同时又将回文的长度分为奇数和偶数,奇数的中心有一个,而偶数的中心有两个.
有一個規律:
- 回文串左右兩邊同時去掉一個字符仍然是回文串;反之一個字符串不是回文串,
- 那麽他左右兩邊不論加上什麽字符都不可能是回文串.
1 | public int countSubstrings(String s) { |
C++实现
1 | class Solution { |