算法 -- 四种方法获取的最长“回文串”,并对时间复杂进行分析对比&PHP
https://blog.csdn.net/hongyuancao/article/details/82962382
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。 -- 来自百度百科
关于获取字符串中最长的回文串的算法中,目前有很多算法,本文中主要是用PHP来实现的算法之一。
算法一:暴力解法
暴力计算出所有的字符串并判断。时间复杂度:O(n^3)。
<?php
//1. 判断字符串是否是回文字符串
function isPalindrome($str)
{
if ($str === strrev($str)) {
return ;
} else {
return ;
}
}
//2. 获取一个字符串有多少子串,设置了子串长度最小为2
function getAllSubstring($str)
{
$all_str_arr = [];
for ($i = ; $i < strlen($str); $i++) {
for ($j = ; $j < strlen($str) - $i + ; $j++) {
if (strlen(substr($str, $i, $j)) > ) {
$all_str_arr[] = substr($str, $i, $j);
}
}
}
return $all_str_arr;
}
//3. 获取一维数组中,元素长度最长的一组
function getArrMaxStr($arr)
{
$max = ;
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 = ; $i < $len; $i++) {
$left = $i;
$right = $i + ;
while ($right < $len && $left >= && $str[$left] == $str[$right]) {
if (strlen($max_str) <= $right - $left + ) {
$max_str = substr($str, $left, $right - $left + );
if (is($max_str)) {
$max_arr[] = $max_str;
}
}
$left--;
$right++;
}
}
// 假如得到的回文串 为 奇数,aba,即中点是字符
for ($i = ; $i < $len; $i++) {
$left = $i - ;
$right = $i + ;
while ($right < $len && $left >= && $str[$left] == $str[$right]) {
if (strlen($max_str) <= $right + - $left) {
$max_str = substr($str, $left, $right - $left + );
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 ;
} else {
return ;
}
}
算法三:公共字符串法
利用公共最长字符串,时间复杂度: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 ;
} else {
return ;
}
}
算法四:Manacher算法
经典的Manacher 算法,优势在于避免了算法②奇偶数讨论的问题,简化了算法②边界判断,还记录了当前字符串的“回文状态”,利用之前的回文状态来求当前回文状态 ,体现了算法③动态规划的思想,存储数据,不用再次计算。时间复杂度为O(n)。
function getMaxPalindrome4($str)
{
// 初始化最大回文序列中间坐标
$maxxy = ;
// 初始化最大回文长度
$maxLength = ;
// 初始化一个空数组存储每次的回文序列中间坐标(key)和回文长度(value)
$arr = [];
// 通过在每个字符的两边都插入一个特殊的符号,将所有的回文子串都转换成奇数长度;
// 在字符串的开始和结尾加入另一个特殊字符,这样就不用特殊处理越界问题
$newStr = "^#" . implode("#", str_split($str)) . "#\0";
// 递推,每次取一个数作为中间坐标
for ($i = ; $newStr[$i] != "\0"; $i++) {
// 每个中间坐标的初始回文长度为1
$arr[$i] = ;
// 根据每个中间坐标往两头匹配是否相等
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 + , $maxLength * - );
// 清除开始加入的字符并返回
return str_replace('#', "", $res);
}
总结:由上可以清晰看出,时间复杂度④>③=②>①,算法四是最优方案。
---------------------
作者:hongyuancao
来源:CSDN
原文:https://blog.csdn.net/hongyuancao/article/details/82962382
版权声明:本文为博主原创文章,转载请附上博文链接!
算法 -- 四种方法获取的最长“回文串”,并对时间复杂进行分析对比&PHP的更多相关文章
- 四种方法获取可执行程序的文件路径(.NET Core / .NET Framework)
原文:四种方法获取可执行程序的文件路径(.NET Core / .NET Framework) 本文介绍四种不同的获取可执行程序文件路径的方法.适用于 .NET Core 以及 .NET Framew ...
- Manacher算法 - 求最长回文串的利器
求最长回文串的利器 - Manacher算法 Manacher主要是用来求某个字符串的最长回文子串. 不要被manacher这个名字吓倒了,其实manacher算法很简单,也很容易理解,程序短,时间复 ...
- manacher 算法(最长回文串)
manacher算法: 定义数组p[i]表示以i为中心的(包含i这个字符)回文串半径长 将字符串s从前扫到后for(int i=0;i<strlen(s);++i)来计算p[i],则最大的p[i ...
- 算法笔记_032:最长回文串(Java)
目录 1 问题描述 2 解决方案 2.1 中心扩展法 2.2 Manacher算法 1 问题描述 给定一个字符串,求它的最长回文子串的长度. 2 解决方案 2.1 中心扩展法 此处,首先枚举出回文 ...
- hdu 3068 最长回文 (Manacher算法求最长回文串)
参考博客:Manacher算法--O(n)回文子串算法 - xuanflyer - 博客频道 - CSDN.NET 从队友那里听来的一个算法,O(N)求得每个中心延伸的回文长度.这个算法好像比较偏门, ...
- Manacher's Algorithm 马拉车算法(求最长回文串)
作用:求一个字符串中的最长子串,同时还可以求所有子串的长度. 题目链接: https://vjudge.net/contest/254692#problem/B 最长回文串长度的代码: int Man ...
- 从0打卡leetcode之day 6--最长回文串
题目描述 给定一个字符串 s,找到 s中最长的回文子串.你可以假设 s 的最大长度为1000. 示例1 输入: "babad" 输出: "bab" 注意: &q ...
- MANACHER---求最长回文串
求最长回文串,如果是暴力的方法的话,会枚举每个字符为中心,然后向两边检测求出最长的回文串,时间复杂度在最坏的情况下就是0(n^2),为什么时间复杂度会这么高,因为对于每一个作为中心的字符的检测是独立的 ...
- Leetcode0005--Longest Palindromic Substring 最长回文串
[转载请注明]http://www.cnblogs.com/igoslly/p/8726771.html 来看一下题目: Given a string s, find the longest pali ...
随机推荐
- day_5.29 网络编程QQDemo.
2018-5-29 16:58:13 明天回学校玩几天给郭星辰过生日 实现一个QQDemo (多线程完成,因为那部分视频损坏没看) ''' from threading import Thread f ...
- 使用python爬虫爬取股票数据
前言: 编写一个爬虫脚本,用于爬取东方财富网的上海股票代码,并通过爬取百度股票的单个股票数据,将所有上海股票数据爬取下来并保存到本地文件中 系统环境: 64位win10系统,64位python3.6, ...
- Python数据结构———栈
线性数据结构 当添加一个项目时,它就被放在这样一个位置:在之前存在的项与后来要加入的项之间.像这样的数据集合常被称为线性数据结构. 栈 栈是一个项的有序集合.添加项和移除项都发生在同一“端”,这一端通 ...
- python 利用tkinter模块设计出window窗口(搞笑版)
代码如下 from tkinter import * import tkinter from tkinter import messagebox #定义了一个函数,当关闭window窗口时将会弹出一个 ...
- python金融与量化分析----Jupyter Notebook使用
Jupyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言.在本文中,我们将介绍 Jupyter notebook 的主要特性,以 ...
- A - Calendar
A - Calendar Time Limit:1000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u Submit ...
- 【libreOJ模板】并查集(输入挂,取模与find优化)
1.了解了各种输入挂性orz,找到了一个合适的 2.find用while写能快一倍,并且能被数据卡掉 3.取模只能快十几毫秒,但也能被数据卡掉 取模find双优化是1997mm过的 再加一个性价比较高 ...
- lame音频编码注意的点
1.注意每次编码的PCM数据不能太短,如果太短编码函数长期返回-1这样的错误,将导致编码器彻底失效程序奔溃的问题,经测试32000在3200下稳定,大概1/10码率是没有问题的,具体请自行查询或调试 ...
- mysql 正确清理binlog 删除数据后磁盘空间的
(3条消息)MySQL删除数据后磁盘空间的释放情况 - ZERO - CSDN博客 https://blog.csdn.net/zero__007/article/details/51404091 m ...
- set,env,export,set -x,set -e;
set 用来显示本地变量 env 用来显示环境变量 export 用来显示和设置环境变量 set 显示当前shell的变量,包括当前用户的变量 env 显示当前用户的变量 export 显示当前导出成 ...