Leetcode005. Longest Palindromic Substring
来源:互联网 发布:天刀捏脸数据金木研 编辑:程序博客网 时间:2024/05/29 07:17
题目描述:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: "babad"Output: "bab"Note: "aba" is also a valid answer.
Example:
Input: "cbbd"Output: "bb"题目大意:
求字符串的最长回文子串。
思路:
首先此题最暴力的做法当然是枚举所有子串判断是否回文,O(n³)
是否还有更快的方法?
中心扩展法:观察到所有的回文串都相对于中间的字符对称,所以可以枚举中间字符,然后往两边展开,一旦发现两边不等直接break。这样就省去了暴力做法的判断回文那一步。时间复杂度O(n²)
同样地这题也可以用DP来解。f[i][j]表示s[i]到s[j]是否为回文串。则f[i][j]=f[i+1][j-1]&&s[i]==s[j]。时间复杂度O(n²)。
还能更快吗?
这里可以使用解决回文串问题的经典O(n)算法:Manacher马拉车算法。
算法的思想来源于对上面中心扩展法的优化。中心扩展法在扩展时没有充分利用已遍历的信息,导致一个字符被多次遍历,增加了时间复杂度。
首先,由于来源于中心扩展法,manacher只能处理长度为单数的回文串,所以在字符串每两个字符中间插入一个特殊字符(例如#)。
定义maxr表示当前枚举过的回文串中最右边的字符位置,pos表示maxr所在的回文串的中心,rl[i]表示以i为中心的回文串能向左或向右扩展多少。
当我们枚举到中心位置i时,有两种情况:
1、i<maxr。此时i处于以pos为中心的那个回文串中。
此时由于回文串两边对称的性质,可以直接把rl[i]置为rl[j],然后再在此基础上继续向两边扩展
2、i>maxr
这时i根本没有被遍历过,所以只能从0开始慢慢扩展。
注意到,每有一个新字符被遍历,maxr一定+1,因为maxr左边的字符不需要再被遍历。所以时间复杂度O(n)。
另外,这道题似乎可以用自动机做,不过本蒟蒻并不会。
不得不吐槽一下,关于字符串的算法经常有一些奇怪的名称:马拉车(Manacher),看毛片(KMP),自动AC机(AC自动机)……
代码:
DP(c++):
class Solution {public:// 动规 string longestPalindrome(string s) { bool p[2000][2000] = {0}; // p[i][j]表示s[i~j]是否回文 int len = s.size(); string ans = s.substr(0, 1); for (int i = 0; i < len; i++) { p[i][i] = true; if (i < len - 1 && s[i] == s[i + 1]) { p[i][i + 1] = true; ans = s.substr(i, 2); } } for (int i = 3; i <= len; i++) // 先枚举子串长度 for (int j = 0; j <= len - i; j++) // 再枚举子串开始位置 if (s[j] == s[j + i - 1] && p[j + 1][j + i - 2]) { p[j][j + i - 1] = true; ans = s.substr(j, i); } return ans; }};Manacher(python):
class Solution(object): def longestPalindrome(self, s): """ :type s: str :rtype: str """ s = '$' + '$'.join(s) + '$' # 加特殊字符 rl = [0] * len(s) # rl[i]表示以i为中心的回文串能扩展多远 maxr = pos = maxlen = maxmid = 0 for i in range(len(s)): if i < maxr: rl[i] = min(rl[2 * pos - i], maxr - i + 1) # i的回文长度至少等于i关于pos的对称点 else: rl[i] = 1 while i + rl[i] < len(s) and i - rl[i] >= 0 and s[i + rl[i]] == s[i - rl[i]]: rl[i] += 1 # 中心扩展 if i + rl[i] - 1 > maxr: maxr = i + rl[i] - 1 # 更新maxr的值 pos = i if rl[i] > maxlen: maxlen = rl[i] # 更新答案 maxmid = i return s[maxmid - maxlen + 1: maxmid + maxlen].replace('$', '') # 把之前加的特殊字符去掉
- leetcode005:Longest Palindromic Substring
- leetcode005 Longest Palindromic Substring
- Leetcode005-Longest Palindromic Substring
- LeetCode005 Longest Palindromic Substring
- Leetcode005. Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- LeetCode Longest Palindromic Substring
- LeetCode: Longest Palindromic Substring
- [Leetcode] Longest Palindromic Substring
- Longest Palindromic substring
- [LeetCode] Longest Palindromic Substring
- LeetCode5:Longest Palindromic Substring
- Leetcode : Longest Palindromic Substring
- Longest Palindromic Substring
- Longest Palindromic Substring
- [LeetCode]Longest Palindromic Substring
- leetcode Longest Palindromic Substring
- Longest Palindromic Substring
- java web 实现验证码
- 《三体》诗歌两首——第四维度的鱼
- ffmpeg生成ffplay问题
- poj1258(最小生成树 kruskal算法)
- 【C语言】栈和栈帧,以及栈帧创建和销毁的过程
- Leetcode005. Longest Palindromic Substring
- 关于wamp的某些问题
- 《机器学习》+周志华+第五章习题+5.5实现标准BP算法和累积BP算法
- HTTP 严格传输安全(HSTS)
- bash脚本筛选出根目录下所有ELF文件,并将路径输出
- AC自动机
- 在MyEclipse中修改注释模板
- 项目之后小谈中颖芯片——SH79F166A
- 深度学习与自然语言处理