最长回文子串中心扩散详解
Posted 是渣渣呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长回文子串中心扩散详解相关的知识,希望对你有一定的参考价值。
p(? ,? )表示是否回文,并且 第一个参数是左端点,第二个是右端点
Si 表示字符串中位置i对应的字符
可以发现,所有的状态在转移的时候的可能性都是唯一的。也就是说,我们可以从每一种边界情况开始「扩展」,也可以得出所有的状态对应的答案。
注 :这里的边界不是指左右的边界,而是回文串的中间位置
P(i,j)才是字符串的左右边界,图中的状态转移链相当于从两边向中间倒推到中间的过程!!
边界情况即为子串长度为 1或 2(奇数或者偶数) 的情况。
就相当于 c a b a d 和 a b b c d
我们枚举每一种边界情况,并从对应的子串开始不断地向两边扩展。如果两边的字母相同,我们就可以继续扩展,例如从 P(i+1,j-1)P(i+1,j−1) 扩展到 P(i,j)P(i,j);
如果两边的字母不同,我们就可以停止扩展,因为在这之后的子串都不能是回文串了。
「边界情况」对应的子串实际上就是我们「扩展」出的回文串的「回文中心」。中心扩散算法的本质即为:我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。
注意看注释!!
public String longestPalindrome(String s)
int start = 0, end = 0;//用于标记最长回文子串的首尾下标
for (int i = 0; i < s.length(); i++)
int len1 = expandAround(s, i, i);//这个是对应回文中心为奇数个的情况
int len2 = expandAround(s, i, i + 1);//这个是对应回文中心为偶数个的情况
int len = Math.max(len1, len2);//如果不是对应的参数,那长度肯定会变小,所以大的那个一定是我们要的当前回文中心对应的长度
/**
* 举个例子 :
*
* c a b b d i = 2 时调用 expandAround(s, i, i); ===》len1 = 1
* 对应下标 0 1 2 3 4 但实际上应该是 2 (len2的结果)
*
*
* c a b a d i = 2 时调用 expandAround(s, i, i + 1); ===》 len2 = 0
* 对应下标 0 1 2 3 4 但实际上应该是 3 (len1的结果)
*/
if (len > end - start)
start = i - (len - 1) / 2; // (len-1)/2就表示在长度为2的时候start还是在i的位置,
end = i + len / 2; // 而end在长度为2的时候还是要+1的
return s.substring(start, end + 1);
//用于判断每个回文中心的最长回文子串的长度
public int expandAround(String s, int l, int r)
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r))
l--;
r++;
//当循环结束的时候,l和r所在的位置字符不相等,不在回文串的范围内,所以长度是下标差再 - 1
return r - l - 1;
以上是关于最长回文子串中心扩散详解的主要内容,如果未能解决你的问题,请参考以下文章