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