当前位置: 首页 > news >正文

广东省公路建设有限公司网站北京seoqq群

广东省公路建设有限公司网站,北京seoqq群,哈尔滨做网站seo,网页源代码查看🌠作者:阿亮joy. 🎆专栏:《数据结构与算法要啸着学》 🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉…

🌠作者:@阿亮joy.
🎆专栏:《数据结构与算法要啸着学》
🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述


目录

    • 👉前言👈
    • 👉Manacher 算法👈
    • 👉最长回文子串👈
    • 👉总结👈

👉前言👈

如果给定一个字符串 str,如何求解该字符串的最长回文子串(注:子串必须是连续的,子序列不要求连续)。如字符 str 为 abc12320d1,其最长回文子串是 232,而不是 回文子序列 12321。如果一个字符串是回文串,那么该字符串一定有个对称轴,使得左右两边的字符是对称的。比如:字符串 abcba 的对称轴是字符 c(实轴),字符串 abba 的对称轴是一条虚轴(不是关于某个字符对称)。

那么我们要求字符串的最长回文子串,我们很容易想到一种暴力的方法:遍历字符串的每一个字符,从该字符为中心向左右两边扩(左边和右边的字符相等就扩,不相等就停止),这样就能得到最长回文子串了。这种方法的时间复杂度是 O(N^2),非常的暴力,而且这种方法不能够解决字符串长度为偶数的情况。如:字符串 122131221,因为回文串长度为偶数时,其对称轴是虚轴,这样就无法保证每个字符向左右两边扩都能得到以该字符为中心的最长回文串。

那如何保证能够得到偶数的回文串呢?这就需要学习本篇博客要介绍的 Manacher 算法。

👉Manacher 算法👈

Manachar 算法主要是处理字符串中关于回文串的问题的,它可以在 O(N) 的时间处理出以字符串中每一个字符为中心的回文串半径,由于将原字符串处理成两倍长度的新串,在每两个字符之间加入一个特定的特殊字符,因此原本长度为偶数的回文串就成了以中间特殊字符为中心的奇数长度的回文串了。

Manacher 算法提供了一种巧妙的办法,将长度为奇数的回文串和长度为偶数的回文串一起考虑。具体做法是:在原字符串的每个相邻两个字符中间插入一个分隔符,同时在首尾也要添加一个分隔符,分隔符可以是原串中的子串,但一般情况下都是使用 # 号作为分隔符。


在这里插入图片描述
如果 Manacher 算法也像上图的做法来求最长回文子串的话,那么它的时间复杂度也是 O(N^2),那 Manacher 算法是如何将时间复杂度优化到 O(N) 的呢?我们一起来看一下!

Manacher 算法的优化就是通过已知信息来做到时间复杂度的优化。首先,我们需要知道回文半径和回文直径的概念。见下图所示:

在这里插入图片描述
知道回文半径和回文直径后,我们还需要知道一个概念—— 回文半径数组,就是我们将已经求得的回文半径放在数组中,那么该数组就被称为回文半径数组。还有最后两个概念,一个是回文右边界,另一个是回文中心。回文中心比较好理解,就是回文串的中心点下标。回文右边界是以每个字符为中心扩出来的回文串的右边界,它是一个整型。在扩的过程中,如果新生成的回文串的右边界比原来右边界还要右,这时候就需要更新回文右边界;否则不需要更新。如果回文右边界更新,回文中心就需要更新;而如果回文右边界没有更新,回文中心也不需要更新。

在这里插入图片描述

知道了上面的全部概念后,我们就来学习 Manacher 算法。Manacher 算法在更新回文数组的时候,会遇到两种情况:字符的下标超出回文右边界和字符的下标在回文右边界的范围内。

当字符的下标超出回文右边界时,我们就以该字符为中心向左右暴力两边扩,然后更新回文右边界。

在这里插入图片描述
当字符的下标在回文右边界的范围内,这时候就可以通过已用的信息(回文数组)来进行优化了。

在这里插入图片描述

字符下标在回文右边界内这种情况又可以根据 i’ 回文区域的不同分为三个小类:

  • 第一小类:i’ 的整个回文区域都在 left 到 right 的范围内

在这里插入图片描述

  • 第二小类:i’ 回文区域的左边界小于 left

在这里插入图片描述

  • 第三小类:i’ 回文区域的左边界等于 left

在这里插入图片描述

Manacher 算法伪代码

// 返回值是回文半径数组
vector<int> Manacher(string& s)
{// 1221 -> #1#2#1#2#1#s 经过处理变成了 strvector<int> pArr(str.size(), 0);	// 回文半径数组int right = -1;	//回文右边界int center = -1;	// 回文中心for(int i = 0; i < str.size(); ++i){if(i在right的外部){以i为中心,向左右两边暴力扩,回文右边界right变大}else{if(i'的回文区域在left到right范围内){pArr[i] = pArr[2 * center - i]	// 堆成性质}else if(i'回文区域的左边界小于left){pArr[i] = right  + 1 - i;	// 加一的原因是回文半径需要加上中心点i}else	// i'回文区域的左边界等于left{从right范围之外的字符开始往外扩,然后确定回文半径pArr[i]第一次扩失败了,回文右边界right不变否则,回文右边界right变大}}}return pArr;
}

很显然,Manacher 算法的时间复杂度是 O(N)。

👉最长回文子串👈

在这里插入图片描述
根据 Manacher 算法的伪代码,我们可以改成以下的精简版本的代码

class Solution 
{
public:string longestPalindrome(string s) {// babad --> #b#a#b#a#d// 加入分隔符#string tmp = "#";for(auto ch : s){tmp += ch;tmp += "#";}vector<int> pArr(tmp.size(), 0);    // 回文半径数组int center = -1;   // 回文中心int right = -1;    // 回文右边界的再往右一个位置,最右的回文区域是R-1位置int start = 0;     // 最长回文子串的左边界int end = -1;      // 最长回文子串的右边界int Max = INT_MIN; // 最长回文子串的半径,即最长回文串的直径 / 2 + 1// 那么 Max - 1 就是原字符串的最长回文子串的长度// 每个位置都要求回文半径int size = tmp.size();for(int i = 0; i < size; ++i){// i至少的回文区域,先更新给pArr[i]// 不需要扩就能知道i的最小回文区域// i在right外时,需要暴力扩,i的回文区域至少包括自己// i在right内,第一小类和第二小类是能够直接拿到的// 对于第一和第二小类,i的回文半径是(pArr[2 * center - 1]、right - i)中的较小值pArr[i] = right > i ? min(pArr[2 * center - i], right - i) : 1;// 第三小类是需要向左右两边扩才能确定的往,循环条件保证往外扩时不越界// 第一和第二小类第一次扩就会扩失败while(i + pArr[i] < size && i - pArr[i] > -1){if(tmp[i + pArr[i]] == tmp[i - pArr[i]])++pArr[i];elsebreak;}// 更新回文右边界和回文中心if(i + pArr[i] > right){right = i + pArr[i];center = i;}// 注:i+pArr[i]大于right并不意味着以i为中心的回文子串就是最长的回文子串// 而如果以i为中心的回文子串就是最长的子串,那么i+pArr[i]一定大于right// 更新最长回文子串的半径、左边界和右边界if(pArr[i] > Max){Max = pArr[i];// 因为right是回文右边界的下一个位置,且最长回文子串// 的左边界加右边界等于两倍的center,所以可以推出// start + right - 1 = 2 * centerstart = 2 * center + 1 - right;end = right - 1;}}// 将最长回文子串还原出来// Max - 1 和 (end + 1 - start) / 2都是最长回文子串的长度string ret;for(int i = start; i <= end; ++i){if(tmp[i] != '#')ret += tmp[i];}return ret;}
};

在这里插入图片描述

👉总结👈

本篇博客主要讲解什么是 Manacher 算法以及 Manacher 算法是如何求解最长回文子串的。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

http://www.tj-hxxt.cn/news/69375.html

相关文章:

  • 大型建设网站制作如何优化网页
  • 电子商务网站开发费用调研报告抖音seo关键词优化
  • 说明网站建设与网站运营的区别百度一键安装
  • 创新的网站建站今日新闻国际头条新闻
  • 学校建设外文网站情况营销案例100例简短
  • 网站建设 宁夏怎样做一个自己的网站
  • 祥云网站优化世界球队最新排名榜
  • 做网站怎么赚钱 111推广策划方案范文
  • 太原市给企业做网站自己动手建立个人网站
  • 自己弄公司网站西安网站建设推广优化
  • 网站的图片滚动怎么做的潍坊网站建设seo
  • 像优酷平台网站是怎么做的品牌营销做得好的品牌有哪些
  • python做网站缺点精准防恶意点击软件
  • 做网站 给源代码微信朋友圈广告推广
  • 合肥专业建站网站关键字优化价格
  • wordpress bat高亮网络seo首页
  • 武汉三网合一网站建设怎么让付费网站免费
  • 优酷网站建设视频教程集上海公司排名
  • 山东网站建设好不好长春网站建设解决方案
  • 360免费建站不要钱百度统计代码
  • 潍坊专业人员继续教育网络平台登录沙洋县seo优化排名价格
  • 网站建设与管理难学吗搜索量排名
  • 套做网站百度总部在哪里
  • 百度网站流量统计灰色词优化培训
  • 西安网站开发公司电话网站优化推广培训
  • 做网站 要学 什么语言经典营销案例
  • 局域网的电脑怎么做网站服务器2021十大网络舆情案例
  • 万户网络技术有限公司长春seo结算
  • 中国wix网站制作公司百度品牌推广
  • 电子商务网站建设毕业论文腾讯广告联盟