leetcode 5. Longest Palindromic Substring
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
lens=len(s)
dp = [[0 for i in range(lens)] for i in range(lens)]
for i in range(0,lens):
for j in range(0,lens):
dp[i][j]=0
for i in range(0,lens):
dp[i][i]=1
mx=0
x=0
y=0
for j in range(1,lens):
i=0
while(i+j<lens):
if s[i]==s[i+j] and i+1<lens and dp[i+1][i+j-1]!=-1:
dp[i][i+j]=dp[i+1][i+j-1]+2
else:
dp[i][i+j]=-1
if dp[i][i+j]>mx:
mx=dp[i][i+j]
x=i
y=i+j
i=i+1
ans=s[x:y+1]
return ans
字符串处理的经典问题,可以使用动态规划的区间dp解决
这里使用python写了一个区间dp,基本思想是如果s[i+1:j+i]是一个回文串或空串的话,那么dp[i][j+i]=dp[i+1][j+i-1]+2
当然还有很多的方法比如
枚举法:n*n
枚举字符串的对称轴,用两个指针从中间向外拓展,遇到有相同的字符串时就停止
manacher:O(n)
首先在两个字符中间插入一个特殊字符,如同这样:# a # b # a #
然后每一个字符就相当于一个对称轴了,我们可以就此跑n*n的算法,但可以不满足于此
令f[i] 表示以第i个字符为中心的最长回文子串的长度,枚举回文串的中心位置,统计使得回文串右边界(j + f(j) / 2)最大的那个j,然后再计算每一个i的时候,都可以通过f(i)≥min{f(2*j-i), f(j)-2*(i-j)}这个公式来知道f(i)的一个最小值
简单的说,我们记录一个每次能访问到最远端点,然后枚举下一个中心结点时利用我们的公式推知那个最小值,每次就从那个最小值开始访问就行了
当然我们获得的长度最后还要减去特殊字符
示例代码:(来源于互联网)
其中p数组存的是中心结点最长回文串的半径
void pk()
{
int i;
int mx = 0;
int id;
for(i=1; i<n; i++)
{
if( mx > i )
p[i] = MIN( p[2*id-i], mx-i );
else
p[i] = 1;
for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
;
if( p[i] + i > mx )
{
mx = p[i] + i;
id = i;
}
}
}
当然还有一些复杂的数据结构AC自动机,后缀自动机这样的东西可以使用
不过更加好用的要算回文自动机了,相关链接:http://www.cnblogs.com/crazyacking/p/4742400.html
浙公网安备 33010602011771号