比如 abcd,最长a。abcba,最长 abcba。
第一种暴力破解法,截取所有的子串,分别判断。
第二种中心扩散法,回文串有两种可能,分别是aba和aa两种可能。对每一个字符,截取本身做中心扩散,再截取本身和下一个字符做中心扩散。最后找到最长回文子串。注意边界条件。
第三种动态规划法
状态:dp[i][j] 表示子串 s[i…j]是否是回文子串
状态转移方程:
dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]
边界条件: j-1 - (i+1) + 1 < 2, 整理得 j-i < 3. 也就是说,j-i < 3时,状态转移方程不再适用。
初始化:dp[i][i] = true(当然这里的值不会被参考到)
输出:在得到一个状态的值为true后,记录起始位置和长度,填表后再截取。
考虑边界条件后的状态转移方程:
dp[i][j] = (s[i] == s[j]) && (j - i <3 || dp[i+1][j-1])
假设字符为: b a b a b
由状态转移方程,看出dp[i][j] 依赖它左下方的值。所以我们的填表顺序为:
先升序填列,再升序填行。
又因为 i < j。所以我们只需要填上半部分表格。
从这个例子也可以看出,动态规划法是典型的空间换时间,先解决小规模问题,逐步解决大规模问题。
第四种终极算法:Manacher算法!(马拉车算法!)
专门用于查找最长回文子串,时间复杂度O(n),空间复杂度O(n).
将原始字符串进行预处理,在预处理字符串上执行动态规划和中心扩散法。用到再说。