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

关于申请建设门户网站的湖北城市建设职业技术学院教务网站

关于申请建设门户网站的,湖北城市建设职业技术学院教务网站,制作网站专业公司吗,四川省建设工程质量安全网站最长回文子串问题-Manacher算法深度解析 一、最长回文子串问题概述1.1 问题定义1.2 传统解法及其局限性 二、Manacher 算法核心原理2.1 算法设计思想2.2 字符串预处理2.3 辅助数组与回文半径2.4 利用对称性优化计算 三、Manacher 算法实现步骤四、Manacher 算法代码实现4.1 Pyt…

最长回文子串问题-Manacher算法深度解析

    • 一、最长回文子串问题概述
      • 1.1 问题定义
      • 1.2 传统解法及其局限性
    • 二、Manacher 算法核心原理
      • 2.1 算法设计思想
      • 2.2 字符串预处理
      • 2.3 辅助数组与回文半径
      • 2.4 利用对称性优化计算
    • 三、Manacher 算法实现步骤
    • 四、Manacher 算法代码实现
      • 4.1 Python 实现
      • 4.2 Java 实现
      • 4.3 C++ 实现
    • 五、复杂度分析
      • 5.1 时间复杂度
      • 5.2 空间复杂度

求解最长回文子串的传统方法如暴力枚举、动态规划虽然能解决问题,但在时间复杂度上存在一定局限。Manacher 算法以其巧妙的预处理方式和利用回文串对称性的优化策略,高效地解决了最长回文子串问题,将时间复杂度从传统方法的 O ( n 2 ) O(n^2) O(n2) O ( n 3 ) O(n^3) O(n3) 降低到了 O ( n ) O(n) O(n)。本文我将详细介绍 Manacher 算法的原理、实现步骤、代码示例、复杂度分析以及实际应用场景,带你全面掌握这一算法。

一、最长回文子串问题概述

1.1 问题定义

回文串是指一个字符串从左往右读和从右往左读是一样的,例如 “aba”、“noon” 等。最长回文子串问题就是在给定的字符串中,找出长度最长的回文子串。如果存在多个长度相同的最长回文子串,返回其中任意一个即可。例如,对于字符串 “babad”,最长回文子串是 “bab” 或 “aba”;对于字符串 “cbbd”,最长回文子串是 “bb”。

1.2 传统解法及其局限性

  • 暴力枚举法:通过两层循环枚举所有可能的子串,然后判断每个子串是否为回文串,时间复杂度为 O ( n 3 ) O(n^3) O(n3),其中 n n n 是字符串的长度。这种方法虽然简单直观,但在处理长字符串时效率极低。

  • 动态规划法:利用动态规划的思想,定义状态 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示字符串中从索引 i i i 到索引 j j j 的子串是否为回文串,通过状态转移方程 d p [ i ] [ j ] = ( s [ i ] = = s [ j ] ) ∧ d p [ i + 1 ] [ j − 1 ] dp[i][j] = (s[i] == s[j]) \land dp[i + 1][j - 1] dp[i][j]=(s[i]==s[j])dp[i+1][j1] 来计算,时间复杂度可以优化到 O ( n 2 ) O(n^2) O(n2),空间复杂度也为 O ( n 2 ) O(n^2) O(n2)。虽然有所改进,但在效率上仍有提升空间。

二、Manacher 算法核心原理

2.1 算法设计思想

Manacher 算法的核心思想是通过对字符串进行预处理,将奇数长度和偶数长度的回文串统一处理,并利用已经计算出的回文子串信息,减少重复计算,从而将时间复杂度降低到 O ( n ) O(n) O(n)

2.2 字符串预处理

为了将奇数长度和偶数长度的回文串统一处理,Manacher 算法对原始字符串进行预处理。具体做法是在每个字符的两边都插入一个特殊字符(通常用 ‘#’),并且在字符串的开头和结尾再分别插入一个不同的特殊字符(例如 ‘$’ 和 ‘@’),以确保边界情况的正确处理。例如,对于字符串 “aba”,预处理后变为 “$#a#b#a#@”;对于字符串"abba",预处理后变为"$#a#b#b#a#@"。

经过预处理后,所有的回文子串长度都变为奇数,这样就可以用统一的方式来处理不同长度的回文串,简化了算法的实现。

2.3 辅助数组与回文半径

Manacher 算法引入一个辅助数组 p [ ] p[] p[],其中 p [ i ] p[i] p[i] 表示以字符 s [ i ] s[i] s[i] 为中心的最长回文子串的半径(包括字符 s [ i ] s[i] s[i] 本身)。例如,对于预处理后的字符串 "KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲a#b#b#a#@",p 数组的值可能为 [ 1 , 2 , 1 , 2 , 5 , 2 , 1 , 2 , 1 ] ,其中 数组的值可能为 [1, 2, 1, 2, 5, 2, 1, 2, 1],其中 数组的值可能为[1,2,1,2,5,2,1,2,1],其中p [4] = 5$ 表示以字符 ‘#’(位于原始字符串 “abba” 的中间位置)为中心的最长回文子串的半径为 5,对应的回文子串为 “#b#b#”,去除特殊字符后就是原始字符串中的 “bb”。

2.4 利用对称性优化计算

Manacher 算法的关键优化在于利用已经计算出的回文子串的对称性。假设在计算 p [ i ] p[i] p[i] 时,已经计算出了 p [ 0 ] p[0] p[0] p [ i − 1 ] p[i - 1] p[i1] 的值,并且已知在 i i i 之前存在一个回文子串,其中心为 i d id id,半径为 m x mx mx(即 m x = i d + p [ i d ] mx = id + p[id] mx=id+p[id],表示该回文子串的右边界)。

  • 情况一::此时, i i i 关于 i d id id 的对称点为 j = 2 ∗ i d − i j = 2 * id - i j=2idi。根据回文串的对称性, p [ i ] p[i] p[i] 至少等于 m i n ( p [ j ] , m x − i ) min(p[j], mx - i) min(p[j],mxi)。这是因为如果 p [ j ] p[j] p[j] 小于 m x − i mx - i mxi,那么以 i i i 为中心的回文子串完全包含在以 i d id id 为中心的回文子串内,所以 p [ i ] p[i] p[i] 可以直接取 p [ j ] p[j] p[j];如果 p [ j ] p[j] p[j] 大于等于 m x − i mx - i mxi,那么以 i i i 为中心的回文子串最多只能扩展到 m x mx mx 的位置,所以 p [ i ] p[i] p[i] m x − i mx - i mxi

  • 情况二::此时无法利用对称性,只能从 i i i 为中心,向两边逐个字符进行比较,计算 p [ i ] p[i] p[i] 的值。

三、Manacher 算法实现步骤

  1. 字符串预处理:在原始字符串的每个字符两边插入特殊字符 ‘#’,并在开头和结尾插入其他特殊字符,得到预处理后的字符串 s s s

  2. 初始化辅助数组:创建一个与预处理后字符串长度相同的数组 p p p,并初始化为 0。

  3. 初始化变量:设置变量 i d = 0 id = 0 id=0 表示当前已知的回文子串中心, m x = 0 mx = 0 mx=0 表示当前已知的回文子串的右边界。

  4. 遍历字符串计算 **** **** 数组

  • 对于每个字符 s [ i ] s[i] s[i],如果 i < m x i < mx i<mx,根据对称性计算 p [ i ] p[i] p[i] 的初始值;否则将 p [ i ] p[i] p[i] 初始化为 1。

  • s [ i ] s[i] s[i] 为中心,向两边扩展,比较字符是否相同,更新 p [ i ] p[i] p[i] 的值。

  • 如果以 i i i 为中心的回文子串的右边界超过了当前的 m x mx mx,更新 i d = i id = i id=i m x = i + p [ i ] mx = i + p[i] mx=i+p[i]

  1. 找出最长回文子串:遍历 p p p 数组,找到最大的 p [ i ] p[i] p[i] 值,其对应的回文子串就是原始字符串中的最长回文子串。根据 p [ i ] p[i] p[i] i i i 的值,可以计算出原始字符串中最长回文子串的起始位置和长度。
    马拉车

四、Manacher 算法代码实现

4.1 Python 实现

def manacher(s):# 字符串预处理s = '$#' + '#'.join(s) + '#@'p = [0] * len(s)id, mx = 0, 0for i in range(1, len(s) - 1):if i < mx:p[i] = min(p[2 * id - i], mx - i)else:p[i] = 1# 向两边扩展while s[i - p[i]] == s[i + p[i]]:p[i] += 1# 更新id和mxif i + p[i] > mx:id, mx = i, i + p[i]# 找出最长回文子串max_len, center_index = 0, 0for i in range(1, len(s) - 1):if p[i] - 1 > max_len:max_len = p[i] - 1center_index = istart = (center_index - max_len) // 2return s[start * 2 + 1: start * 2 + 1 + max_len]# 测试
s = "babad"
print(manacher(s))

4.2 Java 实现

public class ManacherAlgorithm {public static String manacher(String s) {// 字符串预处理StringBuilder sb = new StringBuilder();sb.append("$#");for (char c : s.toCharArray()) {sb.append(c).append("#");}sb.append("@");s = sb.toString();int[] p = new int[s.length()];int id = 0, mx = 0;for (int i = 1; i < s.length() - 1; i++) {if (i < mx) {p[i] = Math.min(p[2 * id - i], mx - i);} else {p[i] = 1;}// 向两边扩展while (s.charAt(i - p[i]) == s.charAt(i + p[i])) {p[i]++;}// 更新id和mxif (i + p[i] > mx) {id = i;mx = i + p[i];}}// 找出最长回文子串int maxLen = 0, centerIndex = 0;for (int i = 1; i < s.length() - 1; i++) {if (p[i] - 1 > maxLen) {maxLen = p[i] - 1;centerIndex = i;}}int start = (centerIndex - maxLen) / 2;return s.substring(start * 2 + 1, start * 2 + 1 + maxLen);}public static void main(String[] args) {String s = "babad";System.out.println(manacher(s));}
}

4.3 C++ 实现

#include <iostream>
#include <string>
using namespace std;string manacher(string s) {// 字符串预处理string t = "$#";for (char c : s) {t += c;t += '#';}t += '@';int n = t.size();int p[n];int id = 0, mx = 0;for (int i = 1; i < n - 1; i++) {if (i < mx) {p[i] = min(p[2 * id - i], mx - i);} else {p[i] = 1;}// 向两边扩展while (t[i - p[i]] == t[i + p[i]]) {p[i]++;}// 更新id和mxif (i + p[i] > mx) {id = i;mx = i + p[i];}}// 找出最长回文子串int maxLen = 0, centerIndex = 0;for (int i = 1; i < n - 1; i++) {if (p[i] - 1 > maxLen) {maxLen = p[i] - 1;centerIndex = i;}}int start = (centerIndex - maxLen) / 2;return s.substr(start, maxLen);
}int main() {string s = "babad";cout << manacher(s) << endl;return 0;
}

五、复杂度分析

5.1 时间复杂度

Manacher 算法通过一次遍历预处理后的字符串来计算辅助数组 p p p,在遍历过程中,对于每个字符,虽然存在扩展的操作,但由于每个字符最多被访问两次(一次是计算初始值,一次是扩展),所以整个算法的时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是预处理后字符串的长度,由于预处理后的字符串长度与原始字符串长度是线性关系,所以对于原始字符串,时间复杂度同样为 O ( n ) O(n) O(n)。相较于暴力枚举法和动态规划法,Manacher 算法在时间效率上有了显著提升。

5.2 空间复杂度

算法主要使用了辅助数组 p p p 和一些额外的变量,辅助数组的长度与预处理后字符串的长度相同,所以空间复杂度为 O ( n ) O(n) O(n),其中 n n n 是预处理后字符串的长度。

That’s all, thanks for reading!
觉得有用就点个赞、收进收藏夹吧!关注我,获取更多干货~

http://www.dtcms.com/wzjs/813874.html

相关文章:

  • 企业网站的设计要点毕设 网站开发的必要性
  • flash 网站头部企业系统建设
  • 浏览器怎么打开网站服务器下载net网站开发JD
  • 自己做网站需要学什么软件做外贸有哪些免费的网站有哪些
  • 三星企业网站建设ppt资源下载wordpress
  • 一键开启网站网站建设的可行性报告范文
  • 在什么网站做调查问卷平面广告设计培训班费用
  • 北京丰台网站优化科技网站首页
  • 马鞍山网站建设兼职如何建设好医院网站
  • 湖北二师网站建设排名网站建设的电话销售好做吗
  • 网页导航网站设计ui设计界面配色
  • HTML5做网站例子高端型网站建设
  • 网站毕业设计怎么做网页设计流程是什么
  • 乐器产品主要在什么网站做推广网站后台编辑不了
  • 门户网站建设方案 模板网站的建设的含义
  • 坪山住房及建设局网站个人怎么创建公众号
  • 个人网站备案麻烦湘潭做网站 定制磐石网络
  • 武进区城乡建设局网站四川省级建设主管部门网站
  • 简单写文章的网站html5 网站模板 米
  • 接工程网站广西企业响应式网站建设设计
  • 建设网站石家庄赤壁网站开发
  • 做旅游网站的要求宁波技术好的企业网站制作
  • 做钢材的网站湖南建设职称报考在哪个网站
  • 广州建网站有哪些丽水市做网站的
  • 网站服务器怎么更换网站排名第一
  • 设计师常去的网站国外ip地址
  • 蚌埠百度做网站大理 网站建设
  • 大理公司网站建设企业常见问题及解决方案
  • 做房产网站能赚钱吗公司注册核名流程
  • 服务器怎么建网站网站开发包