您的位置:首页 > 其它

实用算法实现-第 8 篇 后缀树和后缀数组 [4 最长回文子串]

2011-10-16 13:31 330 查看

8.5 最长回文子串

定义字符串S的逆序为S’,有S’[i]=S[n - i - 1](0 ≤ i < len(S),下文所有i处于这个区间内)。其中len(S)为S的长度。如果S和S’相同,则称S为回文串(Palindrome)。S的最长回文子串就是S的所有子串中是回文串且长度最长的字符串。

定义Suffix(S, i)为S以S[i]开头且包含S[i]的后缀字符串。

定义Prefix(S, i)为S以S[i]结尾且包含S[i]的后缀字符串。

令n = Len(S)

可知有如下性质:

1. Len(S’) = Len(S) = n;

2. Len(Suffix(S, i)) = Len(S) - i;

3. Len(Prefix(S, i)) = i;

4. Prefix(S, i) = Suffix’(S’, len(S) - i- 1);

5. Suffix(S, i) = Prefix’(S’, len(S) - i- 1);

6. (S’)’ = S.

要求S的最长回文子串,可以对i在区间[0, len(S))内枚举,找出以S[i]为中心字符的最长回文子串。所有这些回文子串中最长的那个就是S的最长回文子串。

求以S[i]为中心字符的最长回文子串的问题可以描述为:

求一对下标(j, k),满足下列条件:

1. 0 ≤ j ≤ i, i ≤ k < len(S)。因为j,k是S的下标,且一个比i小,一个比i大。

2. i - j = k - i = x。因为所求字符串以S[i]为中心字符。

3. Suffix’(Prefix(S, i), j) = Prefix(Suffix(S,i), k - i) = T。因为所求字符串为回文字符串。

4. x最大

可知在满足条件1的情况下,有:

Suffix’(Prefix(S, i), j)

= Prefix’’(Prefix’(S, i), Len(Prefix(S,i)) - j - 1) 性质5

= Prefix’’(Prefix’(S, i), i + 1 - j - 1) 性质3

= Prefix(Prefix’(S, i), i - j) 性质6

= Prefix(Suffix’’(S’, Len(S) - i - 1), i- j) 性质4

= Prefix(Suffix(S’, Len(S) - i - 1), i -j) 性质6

= Prefix(Suffix(S’, Len(S’) - i - 1), i -j) 性质1

= Prefix(Suffix(S’, n - i - 1), i - j)

所以第三个条件转化为:

Prefix(Suffix(S’, n - i - 1), i - j) = Prefix(Suffix(S,i), k - i)

又由于有条件2,进一步写为:

Prefix(Suffix(S’, n - i - 1), x) =Prefix(Suffix(S, i), x) = T

观察该条件,可知T是Suffix(S, i)和Suffix(S’, n - i - 1)的公共前缀。进一步地,要满足条件4,使x最大,就是使得公共前缀T最长。该最大公共前缀就是所求的以S[i]为中心字符的最长回文子串。

而求一个串的两个后缀的最长公共前缀正是后缀数组所擅长的事情,后缀数组可以在线性的预处理时间后支持O(1)的LCP询问。

所以求以S[i]为中心字符的最长回文子串的方法即为:构建字符串W = S?S',其中?是S的字符表中不存在的字符。在W中,S[i]对应W[i],S'[n - i - 1]对应W[n + 1 + n - i - 1] = W[2n - i]。故此SA[rank(i)]和SA[rank(2n - i)]的最长公共前缀就是最长回文子串,LCP(rank(i), rank(2n- i))就是最长回文子串的长度max(x)。

8.6 实例

8.6.1 最长公共子串

PKUJudgeOnline, 3450, Corporate Identity.

PKUJudgeOnline, 3080, Blue Jeans.

8.6.2 两个串的最长公共子串

PKUJudgeOnline, 2774, Long Long Message.

本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐