最长回文子串(动规,中心扩散法,Manacher算法)
题目
leetcode:5. Longest Palindromic Substring
解法
动态规划
时间复杂度\(O(n^2)\),空间复杂度\(O(n^2)\)
基本解法直接看代码
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n, true));
int rx, ry;
rx = ry = 0;
for(int l = 1; l < n; l++){
for(int i = 0; i < n - l; i++){
int j = i + l;
if(s[i] == s[j] && (j - i < 3 || dp[i+1][j-1])){
dp[i][j] = true;
if(j - i > ry - rx){
ry = j;
rx = i;
}
} else {
dp[i][j] = false;
}
}
}
return s.substr(rx, ry - rx + 1);
}
};
中心扩散法
时间复杂度\(O(n^2)\),空间复杂度\(O(1)\)
我们先假定以某点为中心向两端扩散,找到以该点为中心的最长回文子串
class Solution {
public:
int rx, ry;
void helper(string &s, int i, int offset){
int left = i;
int right = i + offset;
while(left >= 0 && right < s.size() && s[left] == s[right]){
left--;
right++;
}
if(right - 1 - (left + 1) > ry - rx){
ry = right - 1;
rx = left + 1;
}
}
string longestPalindrome(string s) {
int n = s.size();
rx = ry = 0;
for(int i = 0; i < n; i++){
helper(s, i, 0);
helper(s, i, 1);
}
return s.substr(rx, ry - rx + 1);
}
};
Manacher算法
Manacher算法俗称“马拉车算法”,时间复杂度\(O(n)\),空间复杂度\(O(n)\)
因为回文字符串都有奇数长度的串和偶数长度的串,为了更好处理这两种情况,可以在字符串中插入一特殊字符'#',使得新字符串长度全变为奇数长度,如"aa"变为"#a#a#",可以再字符串首部加入另一特殊字符'$'和尾部的'@',这样就不用特殊处理越界问题(统一边界处理)
以"122112321"为例经过上一步变成"@#1#2#2#1#1#2#3#2#1#"
Manacher算法使用一个辅助数组r[i]表示以t[i]为中心的最长回文子串的最右字符到t[i]的长度,如以t[i]为中心的最长回文子串为t[low, high],则r[i] = high - i + 1, t[low, high] = 2 * r[i]-1, len数组有一个性质,就是r[i]-1为该回文子串在原串中的长度,证明很简单t[lowl, high]一定是以"#"开头和结尾的,这样插入的"#"是原来串中字符的两倍还多一个,这样原串中最长回文串的长度就为r[i]-1,这样问题就转为求最长的r[i]
计算len数组
算法主要利用了已有的回文子串的特点,减少了查找时间,从左往右计算len[i],同时保存一个之前计算最长回文子串的右端点的最大值R及对应的中心位置c,
- i < R, 则先找i关于c对称点j=2*c-i,则至少r[i] \(\geq\) min(R - i + 1, p[j]), 超出部分再手工匹配
- i >= R, 则不能利用以后的知识做任何假设,只能假定其至少为1,再手工匹配
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if(n == 0) return "";
string ns;
ns.push_back('$');
for(int i = 0; i < n; i++){
ns.push_back('#');
ns.push_back(s[i]);
}
ns.push_back('#');
ns.push_back('@');
n = ns.size();
vector<int> r(n);
int c, R, C, MAX;
R = -1;
MAX = 0;
C = 0;
for(int i = 1; i < n; i++){
r[i] = i < R ? min(r[2 * c - i], R - i + 1) : 1;
while(ns[i + r[i]] == ns[i - r[i]]) r[i]++;
r[i]--;
if(i + r[i] > R){
R = i + r[i];
c = i;
}
if(r[i] > MAX){
MAX = r[i];
C = i;
}
}
return s.substr((C-MAX)/2, r[C]);
}
};
时间复杂度分析
参考
最长回文子串(动规,中心扩散法,Manacher算法)的更多相关文章
- 【转】最长回文子串的O(n)的Manacher算法
Manacher算法 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长.这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文 ...
- Leetcode(5)-最长回文子串(包含动态规划以及Manacher算法)
给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &quo ...
- [LeetCode] 5. 最长回文子串 ☆☆☆(最长子串、动态规划)
最长回文子串 (动态规划法.中心扩展算法) https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang- ...
- 【LeetCode】最长回文子串【动态规划或中心扩展】
给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab"注意: " ...
- 【LeetCode】最长回文子串-中心扩展法
[问题]给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 : 输入: "babad" 输出: "bab" 注意: ...
- 51nod 1088 最长回文子串 【中心拓展法/输出长度和路径】
1088 最长回文子串 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字 ...
- 最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- 最长回文子串(Longest Palindromic Substring)
这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
随机推荐
- Block代码块中使用局部变量注意点
第一次写代码遇到报这个错,实在是想不通为什么,按常理应该是不会有问题,报错的呀??纠结了一会之后只好仔细查看报错原因咯,原来是: 当我们在block代码块中使用局部变量时,就会很容易出现如图的错误. ...
- 【Linux】【一】linux 目录切换、创建目录和文件、编辑目录以及文件(txt)
以下 是在指定目录下创建文件夹目录,以及在该目录下创建txt文件进行编辑,保存. 然后删除相关文件以及目录的命令操作记录. 本操作记录中的命令简单解释: pwd 显示当前路径 ls 显示当前目录下的文 ...
- java:LeakFilling (Linux)
1.Nosql 列数据库,没有update,非关系型数据库: 为了解决高并发.高可扩展.高可用.大数据存储问题而产生的数据库解决方案,就是NoSql数据库. NoSQL,泛指非关系型的数据库,NoS ...
- java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents...
出现这个错误的原因是时区有问题,可以在mysql中执行命令: set global time_zone='+8:00'; 如上是修改为北京时间(GMT+0800). 查看修改: show variab ...
- Linux 使用中history 默认记录数不够用了?
1.默认情况下,系统能保存1000条的历史命令. #echo $HISTSIZE 2.那么1000条不够用,该怎么办呢? #vi /etc/profile 修改HISTSIZE=1000 > ...
- 【C/C++】什么是线程安全
<strong>线程安全</strong>就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不 ...
- 【Python开发】python重命名文件和遍历文件夹操作
当前文件夹下,把所有文件名中的"50076"替换成"50092",用Python实现,代码所下: # encoding: utf-8 import os imp ...
- 浏览器渲染优化4(styles and layout)
你已经学会了查找和解决问题.希望你的js能正常运行了,但这只是制作帧的一小部分.在这节课里,你将处理样式,也就是像开发工具里标记的那样,重新计算样式.学完这节课后,你将学会从样式计算过程中找到性能问题 ...
- hashmap C++实现
hashmap.h #ifndef _HASHMAP_H_ #define _HASHMAP_H_ template<class Key, class Value> class HashN ...
- JS小知识--获取当前日期的时间和上周五时间
获取当前日期的时间和上周五时间 var today=new Date();//获取当前时间var weekday=today.getDay();//获取星期几 var monday=new Da ...