https://blog.csdn.net/hongyuancao/article/details/82962382

“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。 -- 来自百度百科

关于获取字符串中最长的回文串的算法中,目前有很多算法,本文中主要是用PHP来实现的算法之一。

算法一:暴力解法
暴力计算出所有的字符串并判断。时间复杂度:O(n^3)。

<?php
//1.  判断字符串是否是回文字符串
function isPalindrome($str)
{if ($str === strrev($str)) {return 1;} else {return 0;}
}
//2. 获取一个字符串有多少子串,设置了子串长度最小为2
function getAllSubstring($str)
{$all_str_arr = [];for ($i = 0; $i < strlen($str); $i++) {for ($j = 0; $j < strlen($str) - $i + 1; $j++) {if (strlen(substr($str, $i, $j)) > 1) {$all_str_arr[] = substr($str, $i, $j);}}}return $all_str_arr;
}
//3. 获取一维数组中,元素长度最长的一组
function getArrMaxStr($arr)
{$max = 0;foreach ($arr as $k => $v) {if (strlen($arr[$max]) < strlen($v)) {$max = $k;}}return $arr[$max];
}
//4. 取得字符串中,最长的回文串
function getMaxPalindrome1($str)
{if (isPalindrome($str)) {return $str;} else {// 拆分成多个字符串,然后循环比较foreach (getAllSubstring($str) as $k => $v) {if (isPalindrome($v)) {$max_str[] = $v;}}return getArrMaxStr($max_str);}
}

以上四个步骤就是获取字符串中最长的回文串,但是这个算法只适合较短的字符串,由上大家也可以看出,步骤2中求每一个子串时间复杂度O(N^2),步骤4中,再循环判断子串是不是回文串O(N),两者是相乘关系,所以时间复杂度为O(N^3)。

暴力求解的优化:

每次判断一个字符串是否是回文字符串时,将每次的判断结果存存起来,之后再用就不用重新计算了。但需要从后向前遍历,这样才会用得到提前存储的结果。时间复杂度为O(n^2)。(这里就不代码说明了)

算法二:移动中心法
先假设某个位置为回文字符串的中心,然后查询以此位中心的最长回文字符串。遍历中心,即可找到全局最长子串。时间复杂度为O(n^2)。

function getMaxPalindrome2($str)
{if (is($str)) {return $str;} else {$len = strlen($str);// 假如得到的回文串 为 偶数,abba,即中点是空隙$max_str = '';$max_arr = [];for ($i = 0; $i < $len; $i++) {$left = $i;$right = $i + 1;while ($right < $len && $left >= 0 && $str[$left] == $str[$right]) {if (strlen($max_str) <= $right - $left + 1) {$max_str = substr($str, $left, $right - $left + 1);if (is($max_str)) {$max_arr[] = $max_str;}}$left--;$right++;}}// 假如得到的回文串 为 奇数,aba,即中点是字符for ($i = 0; $i < $len; $i++) {$left = $i - 1;$right = $i + 1;while ($right < $len && $left >= 0 && $str[$left] == $str[$right]) {if (strlen($max_str) <= $right + 1 - $left) {$max_str = substr($str, $left, $right - $left + 1);if (is($max_str)) {$max_arr[] = $max_str;}}$left--;$right++;}}// 两个合成一个的话,就是,只有当奇数回文串的大于或等于偶数回文串的时候,$longest_str = [];foreach ($max_arr as $v) {if (strlen($max_str) == strlen($v)) {$longest_str[] = $v;}}return $longest_str;}
}
// 判断字符串是否是回文字符串
function isPalindrome($str)
{if ($str === strrev($str)) {return 1;} else {return 0;}
}

算法三:公共字符串法
​​利用公共最长字符串,时间复杂度:O(n^2)。

ps:方法getLongestSameStr(),在我的这篇文章里:算法 -- 求最长公共字符串&PHP

function getMaxPalindrome3($str)
{//1. 判断是不是回文if (is($str)) return $str;//2. 利用最长公共字符串的方法求$arr = getLongestSameStr($str, strrev($str));return $arr;
}
// 判断字符串是否是回文字符串
function isPalindrome($str)
{if ($str === strrev($str)) {return 1;} else {return 0;}
}

算法四:Manacher算法
经典的Manacher 算法,优势在于避免了算法②奇偶数讨论的问题,简化了算法②边界判断,还记录了当前字符串的“回文状态”,利用之前的回文状态来求当前回文状态 ,体现了算法③动态规划的思想,存储数据,不用再次计算。时间复杂度为O(n)。

function getMaxPalindrome4($str)
{// 初始化最大回文序列中间坐标$maxxy = 0;// 初始化最大回文长度$maxLength = 0;// 初始化一个空数组存储每次的回文序列中间坐标(key)和回文长度(value)$arr = [];// 通过在每个字符的两边都插入一个特殊的符号,将所有的回文子串都转换成奇数长度;// 在字符串的开始和结尾加入另一个特殊字符,这样就不用特殊处理越界问题$newStr = "^#" . implode("#", str_split($str)) . "#\0";// 递推,每次取一个数作为中间坐标for ($i = 2; $newStr[$i] != "\0"; $i++) {// 每个中间坐标的初始回文长度为1$arr[$i] = 1;// 根据每个中间坐标往两头匹配是否相等while ($newStr[$i - $arr[$i]] == $newStr[$i + $arr[$i]]) {// 每匹配成功一次,则当前坐标的最大回文长度加一$arr[$i]++;}// 判断当前回文长度是否大于最大的回文长度,大于则进去if代码块更新最大回文次数和更新最大回文中间坐标if ($arr[$i] > $maxLength) {$maxLength = $arr[$i];//字符串的长度$maxxy = $i;//字符串的末位置坐标
 }}// 截取最大回文长度的字符串
 $res = substr($newStr, $maxxy - $maxLength + 1, $maxLength * 2 - 1);// 清除开始加入的字符并返回return str_replace('#', "", $res);
}

总结:由上可以清晰看出,时间复杂度④>③=②>①,算法四是最优方案。
 
---------------------
作者:hongyuancao
来源:CSDN
原文:https://blog.csdn.net/hongyuancao/article/details/82962382
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://www.cnblogs.com/rxbook/p/10338305.html

算法 -- 四种方法获取的最长“回文串”,并对时间复杂进行分析对比PHP相关推荐

  1. LeetCode 1771. 由子序列构造的最长回文串的长度(最长回文子序)

    文章目录 1. 题目 2. 解题 1. 题目 给你两个字符串 word1 和 word2 ,请你按下述方法构造一个字符串: 从 word1 中选出某个 非空 子序列 subsequence1 . 从 ...

  2. 1112个人赛,最长回文串常见算法讨论

    ps.此贴大部分文字与代码来自网上,我只是取长补短整理了下 S="c a b a"  那么  S' = "a b a c", 这样的情况下 S和 S'的最长公共 ...

  3. 通俗易懂的最长回文串图解、说明及Java代码(中心扩散法和Manacher算法)

    1. 回文串 作为程序员,回文串这个词已经见怪不怪了,就是一个字符串正着读和反着读是一样的,形式如abcdcba.bbaabb.这里涉及到奇回文和偶回文,奇回文指回文串的字符数是奇数,偶回文指回文串的 ...

  4. java 最长回文串_通俗易懂的最长回文串图解、说明及Java代码(中心扩散法和Manacher算法)...

    1. 回文串 作为程序员,回文串这个词已经见怪不怪了,就是一个字符串正着读和反着读是一样的,形式如abcdcba.bbaabb.这里涉及到奇回文和偶回文,奇回文指回文串的字符数是奇数,偶回文指回文串的 ...

  5. Manacher算法 - 求最长回文串的利器

    求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...

  6. python求最大回文数_python最长回文串算法

    给定一个字符串,要求在这个字符串中找到符合回文性质的最长子串.所谓回文性是指诸如 "aba","ababa","abba"这类的字符串,当然 ...

  7. java 最长回文_【Java】【每日算法/刷穿 LeetCode】5. 最长回文子串(中等)

    首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]5. 最长回文子串(中等) 宫水三叶发布于 今天 12:00 题目描述 给你一个字符串 s,找到 s 中最长的回文子串. 示例 ...

  8. 最长回文串 马拉车算法 C++

    最长回文串 LeetCode 5.最长回文串 给你一个字符串 s,找到 s 中最长的回文子串. 示例 1: 输入:s = "babad" 输出:"bab" 解释 ...

  9. 最长回文 HDU - 3068(求最长回文串的长度【马拉车算法Manacher】)

    马拉车算法 Manacher's Algorithm 是用来查找一个字符串的最长回文子串的线性方法,由一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到了 ...

  10. manacher算法----O(n)最长回文串

    manacher算法----O(n)最长回文串 分类:字符串 (126)  (0)  举报  收藏 manacher的时间复杂度为O(n),后缀数组好像可以处理O(nlogn),但是有些变态题目可能卡 ...

最新文章

  1. 【Java】实战Java虚拟机之五“开启JIT编译”
  2. Android中Activity总结
  3. JavaScript强化教程 —— JavaScript 总结
  4. 论中国和欧洲程序员对加班的态度
  5. 《Java8实战》笔记(01):为什么要关心Java8
  6. 修改oracle的表空间文件scn,分享:bbed修改数据文件头推进scn与其他数据文件相同...
  7. Postman接口压力测试
  8. HDU各种比赛题题解(一)
  9. Java EE产生的背景
  10. android emulator虚拟设备之qemu pipe分析(三)
  11. 极光IM即时通讯初探
  12. 软件项目管理(学习笔记)
  13. 浅析银行业如何做数据治理
  14. 压缩照片大小——PPT实现
  15. putty永久设置session
  16. Android Studio插入图片
  17. Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
  18. java字符串去重_java字符串去重方法详解,字符串如何去重?
  19. android手机一些问题
  20. 证明(sinx)/x的极限

热门文章

  1. 冒泡排序(数组排序不用Array.Sort)
  2. 曾经用过的Cookie
  3. java 小总结,以后复习看以看
  4. ASP网页开发重点源代码
  5. 【OpenCV学习笔记】【编程实例】一(VS2010/MFC+OPenCV2.4.7读取图片和摄像头)
  6. 【LeetCode】【数组】题号:*289,生命游戏
  7. 基于 C#遥感图像处理方法(代码实现)
  8. ENVI 不规则多边形shp裁剪后Memory灰色显示问题解决
  9. Gson反序列化详解
  10. 超强阵容实操教学, 0 基础 Flink 训练营免费抢报啦!