leetcode-Longest Palindromic Substring
来源:互联网 发布:windows正版验证网站 编辑:程序博客网 时间:2024/06/05 02:56
LeetCode:Longest Palindromic Substring 最长回文子串
题目链接
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
求字符串的最长回文子串
算法1:暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为O(n^3)
算法2:删除暴力解法中有很多重复的判断。很容易想到动态规划,时间复杂度O(n^2),空间O(n^2),动态规划方程如下:
- dp[i][j] 表示子串s[i…j]是否是回文
- 初始化:dp[i][i] = true (0 <= i <= n-1); dp[i][i-1] = true (1 <= i <= n-1); 其余的初始化为false
- dp[i][j] = (s[i] == s[j] && dp[i+1][j-1] == true)
在动态规划中保存最长回文的长度及起点即可
算法3:以某个元素为中心,分别计算偶数长度的回文最大长度和奇数长度的回文最大长度。时间复杂度O(n^2),空间O(1)
算法4:Manacher算法,时间复杂度O(n), 空间复杂度O(n)
该算法首先对字符串进行预处理,在字符串的每个字符前后都加入一个特殊符号,比如字符串 abcd 处理成 #a#b#c#d#,为了避免处理越界,在字符串首尾加上不同的两个特殊字符(c类型的字符串尾部不用加,因为自带‘\0’),这样预处理后最终变成$#a#b#c#d#^,经过这样处理后有个好处是原来的偶数长度和奇数长度的回文在处理后的字符串中都是奇数长度。假设处理后的字符串为s 此文地址
对于已经预处理好的字符串我们用数组p[i]来记录以字符S[i]为中心的最长回文子串向左/右扩张的长度(包括S[i]),以字符串“12212321”为例,p数组如下
s: $ # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 # ^
p: 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
可以看出,P[i]-1正好是原字符串中回文串的总长度, 如果p数组已知,遍历p数组找到最大的p[i]就可以求出最长回文的长度,也可以求出回文的位置
下面给出求p[]数组的方法:
设id是当前求得的最长回文子串中心的位置,mx为当前最长回文子串的右边界(回文子串不包括该右边界),即mx = id + p[id]。记j = 2*id – i ,即 j 是 i 关于 id 的对称点。
1、 当i < mx 时,如下图。此时可以得出一个非常神奇的结论p[i] >= min(p[2*id - i], mx - i),下面我们来解释这个结论
如何根据p[j]来求p[i]呢,又要分成两种情况
(1.1)当mx – i > p[j], 这时候以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以 P[i] 至少等于 p[j], 后面的再继续匹配。如下图
注:这里其实p[i]一定等于p[j],后面不用再匹配了。因为如果p[i]后面还可以继续匹配,根据对称性,p[j]也可以继续扩展了
(1.2)当mx – i <= p[j], 以S[j]为中心的回文子串不完全包含于以S[id]为中心的回文子串中,但是基于对称性可知,下图中两个绿框所包围的部分是相同的,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] 至少等于 mx - i,至于mx之后的部分是否对称,就只能老老实实去匹配了。
注:如果mx – i < p[j] ,这时p[i]一定等于mx - i, 因为如果p[i]在mx之后还可以继续匹配,根据对称性,mx之后匹配的点(包括mx)一定会出现在my的前面,这说明p[id]也可以继续扩展了
2、当i >= mx, 无法对p[i]做更多的假设,只能p[i] = 1,然后再去匹配
算法复杂度分析:根据斜体字部分的注释,只有当mx-i = p[j]时 以及 i > mx时才要扩展比较,而mx也是在不断扩展的,总体而言每个元素比较次数是n的线性关系,所以时间复杂度为O(n)
public class Solution { public String longestPalindrome(String s) { if(s==null||s.length()==0) return ""; String str=preProcess(s); int[] result=new int[2*s.length()+3]; int id=0;//目前延伸的最远(mx最大)的中心位置 int mx=0;//目前的延伸位置 int maxId=0;//拥有回文长度的中心点 for(int i=1;i<str.length()-1;i++){ result[i]= mx>i?Math.min(result[2*id-i],mx-i):1;//当i超出范围了,就初始化1 while(str.charAt(i-result[i])==str.charAt(i+result[i])) result[i]++; if(mx<i+result[i]){ id=i; mx=i+result[i]; } if(result[maxId]<result[i]){ maxId=i; } } System.out.println("maxId="+maxId+",leng="+(result[maxId]-1) ); return s.substring((maxId - result[maxId])/2, (maxId - result[maxId])/2+result[maxId]-1); } public String preProcess(String s){ StringBuilder sb=new StringBuilder("^"); for(int i=0;i<s.length();i++){ sb.append("#").append(s.charAt(i)); } sb.append("#&"); return sb.toString(); }}Manacher复杂度为什么是O(n)??
参考资料:
Longest Palindromic Substring Part II
Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串
Longest Palindromic Substring | Set 2
【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3675788.html
ps :Manacher算法其时间复杂度为何是O(N) http://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html
- LeetCode: Longest Palindromic Substring
- LeetCode Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- [Leetcode] Longest Palindromic Substring
- [LeetCode] Longest Palindromic Substring
- Leetcode : Longest Palindromic Substring
- [LeetCode]Longest Palindromic Substring
- leetcode Longest Palindromic Substring
- LeetCode-Longest Palindromic Substring
- [LeetCode] Longest Palindromic Substring
- Longest Palindromic Substring leetcode
- LeetCode Longest Palindromic Substring
- LeetCode - Longest Palindromic Substring
- LeetCode -- Longest Palindromic Substring
- LeetCode | Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- [LeetCode]Longest Palindromic Substring
- leetcode Longest Palindromic Substring
- 9.实例剖析
- C#多线程开发4:线程的Abort和ResetAbort方法
- 【C++】派生类对象初始化基类的引用
- java web 中error页面的配置
- Java 设计模式 -- 复合模式之一
- leetcode-Longest Palindromic Substring
- 10块设备驱动程序的编写
- Codeforces Gym 100500E IBM Chill Zone
- threadlocal 作用
- 机器学习--AdaBoost元算法
- 2-19
- 使用strace调试程序
- MFC:RichEdit and CFindReplaceDialog
- matlab调用笔记本摄像头拍照并连续保存