0
点赞
收藏
分享

微信扫一扫

[动态规划]BM73 最长回文子串-中等

​​BM73 最长回文子串​​

描述

对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。


数据范围: [动态规划]BM73 最长回文子串-中等_中心扩展法要求:空间复杂度 [动态规划]BM73 最长回文子串-中等_manacher_02,时间复杂度 [动态规划]BM73 最长回文子串-中等_最长回文子串_03进阶:  空间复杂度 [动态规划]BM73 最长回文子串-中等_中心扩展法_04,时间复杂度 [动态规划]BM73 最长回文子串-中等_中心扩展法_04

示例1

输入:

"ababc"

复制返回值:

3

复制说明:

最长的回文子串为"aba"与"bab",长度都为3

示例2

输入:

"abbba"

复制返回值:

5

复制

示例3

输入:

"b"

复制返回值:

1

题解

中心扩展历解法

思路:

遍历整个字符串,获取以该索引为中心的最长回文字符串长度

时间复杂度:o(n2)

空间复杂度:o(1)

代码如下:

#include <bits/stdc++.h>

int longest(std::string &a, int left_1, int right_1, int left_2, int right_2)
{
int palin_length = 0;
// 边界检查
if (left_1 < 0 || left_2 >= a.size() || left_1 > right_1 || left_2 > right_2)
{
return 0;
}

// 判断回文长度
while (right_1 >= left_1 && left_2 <= right_2)
{
if (a[right_1] == a[left_2])
{
palin_length += 2;
right_1--;
left_2++;
continue;
}
break;
}

return palin_length;
}

int getLongestPalindrome(std::string a)
{
int max_length = 0;
for (int i = 0; i < a.size(); ++i)
{
// 以i为中心有2种回文方式,一种为[0,i]和[i+1,a.size-1]的对称
// 另一种是以i为中心点,[0,i-1]和[i+1,a.size-1]的对称
// 取他们的最长值即可
int length = std::max(longest(a, 0, i - 1, i + 1, a.size() - 1) + 1, longest(a, 0, i, i + 1, a.size() - 1));
max_length = std::max(length, max_length);
}
return max_length;
}

动态规划——manacher解法

以下方法及代码来源于牛客网官方题解


  • step 1:我们用maxpos表示目前已知的最长回文子串的最右一位的后一位,用index表示当前的最长回文子串的中心点。
  • step 2:对于给定的 i 我们找一个和它关于index对称的 j ,也就是[动态规划]BM73 最长回文子串-中等_中心扩展法_06,换言之就是[动态规划]BM73 最长回文子串-中等_中心扩展法_07
  • step 3:i 和 j 的最长回文子串在index的回文串范围内的部分应该是一模一样的,但是在外面的部分就无法保证了,当然,最好的情况是i和j的回文子串范围都很小,这样就保证了它们的回文子串一定一模一样,对于超出的部分我们也没有办法, 只能手动使用中心扩展。
  • step 4:最后答案计算的时候需要考虑使用预处理,长度被加了一倍,于是结果是 max(mp[i]-1)。
class Solution {
public:
//manacher算法
void manacher(string& s, int n, vector<int>& mp){
string ms = "";
ms += "$#";
//预处理
for(int i = 0; i < n; i++){
//使之都变成奇数回文子串
ms += s[i];
ms += '#';
}
//目前已知的最长回文子串的最右一位的后一位
int maxpos = 0;
//当前的最长回文子串的中心点
int index = 0;
for(int i = 0; i < ms.length(); i++){
mp[i] = maxpos > i ? min(mp[2 * index - i], maxpos - i) : 1;
//两边扫
while(ms[i + mp[i]] == ms[i - mp[i]])
mp[i]++;
//更新位置
if(i + mp[i] > maxpos){
maxpos = i + mp[i];
index = i;
}
}
}
int getLongestPalindrome(string A) {
int n = A.length();
//记录回文子串长度
vector<int> mp(2 * n + 2);
manacher(A, n, mp);
int maxlen = 0;
//遍历数组
for(int i = 0; i < 2 * n + 2; i++)
//找到最大的长度
maxlen = max(maxlen, mp[i] - 1);
return maxlen;
}
};
举报

相关推荐

0 条评论