Python实现常见的回文字符串算法


Posted in Python onNovember 14, 2018

回文

利用python 自带的翻转 函数 reversed()

def is_plalindrome(string):  return string == ''.join(list(reversed(string)))`

自己实现

def is_plalindrome(string):
  string = list(string)
  length = len(string)
  left = 0
  right = length - 1
  while left < right:
    if string[left] != string[right]:
      return False
    left += 1
    right -= 1
  return True

最长的回文子串

暴力破解

暴力破解,枚举所有的子串,对每个子串判断是否为回文, 时间复杂度为 O(n^3)

动态规划

def solution(s):
  s = list(s)
  l = len(s)
  dp = [[0] * l for i in range(l)]
  for i in range(l):
    dp[i][i] = True
    # 当 k = 2时要用到
    dp[i][i - 1] = True
  resLeft = 0
  resRight = 0
  # 枚举子串的长度
  for k in range(2, l+1):
    # 子串的起始位置
    for i in range(0, l-k+1):
      j = i + k - 1
      if s[i] == s[j] and dp[i + 1][j - 1]:
        dp[i][j] = True
        # 保存最长的回文起点和终点
        if resRight - resLeft + 1 < k:
          resLeft = i
          resRight = j
  return ''.join(s[resLeft:resRight+1])

时间复杂度为 O(n^2), 空间复杂度为 O(n^2)

Manacher 算法

Manacher 算法首先对字符串做一个预处理,使得所有的串都是奇数长度, 插入的是同样的符号且符号不存在与原串中,串的回文性不受影响

aba => #a#b#a#abab => #a#b#a#b#`

我们把回文串中最右位置与其对称轴的距离称为回文半径,Manacher 算法定义了一个回文半径数组 RL,RL[i]表示以第 i 个字符为对称轴的回文半径,对于上面得到的插入分隔符的串来说,我们可以得到 RL数组

char: # a # b # a #
RL:  1 2 1 4 1 2 1
RL-1: 0 1 0 3 0 1 0
i:   0 1 2 3 4 5 6
char: # a # b # a # b #
RL:  1 2 1 4 1 4 1 2 1
RL-1: 0 1 0 3 0 3 0 1 0
i:  0 1 2 3 4 5 6 7 8

我们还求了 RL[i] - 1: 我们发现 RL[i] -1 正好是初始字符串中以位置i 为对称轴的最长回文长度

所以下面就是重点如何求得 RL 数组了, 可以参考这篇 文章 (讲得比较清晰)

下面是算法实现

def manacher(preS):
  s = '#' + '#'.join(preS) + '#'
  l = len(s)
  RL = [0] * l
  maxRight = pos = maxLen = 0
  for i in range(l):
    if i < maxRight:
      RL[i] = min(RL[2*pos - i], maxRight-i)
    else:
      RL[i] = 1
    while i - RL[i] >= 0 and i + RL[i] < l and s[i - RL[i]] == s[i + RL[i]]:
      RL[i] += 1
    if i + RL[i] - 1 > maxRight:
      maxRight = i + RL[i] - 1
      pos = i
  maxLen = max(RL)
  idx = RL.index(maxLen)
  sub = s[idx - maxLen + 1: idx + maxLen]
  return sub.replace('#', '')

空间复杂度:借助了一个辅助数组,空间复杂度为 O(n)

时间复杂度:尽管内层存在循环,但是内层循环只对尚未匹配的部分进行,对于每一个字符来说,只会进行一次,所以时间复杂度是 O(n)

最长回文前缀

所谓前缀,就是以第一个字符开始

下面的最长回文前缀

abbabbc => abbc
abababb => ababa
sogou => s

将原串逆转,那么问题就转变为求原串的前缀和逆串后缀 相等且长度最大的值 , 这个问题其实就是 KMP 算法 中的 next 数组的求解了

具体求解: 将原串逆转并拼接到原串中, 以'#' 分隔原串和逆转避免内部字符串干扰。

def longest_palindrome_prefix(s):
  if not s:
    return 0
  s = s + '#' + s[::-1] + '$'
  i = 0
  j = -1
  nt = [0] * len(s)
  nt[0] = -1
  while i < len(s) - 1:
    if j == -1 or s[i] == s[j]:
      i += 1
      j += 1
      nt[i] = j
    else:
      j = nt[j]
  return nt[len(s) - 1]

添加字符生成最短回文字符串

这道题其实跟上面基本是一样的,

实例:

aacecaaa -> aaacecaaa # 添加 a
abcd -> dcbabcd # 添加 dcb

我们先求字符串的最长回文前缀, 然后剩余的字符串逆转并拼接到字符串的头部即是问题所求

def solution(s):
  length = longest_palindrome_prefix(s)
  return s[length:][::-1] + s

最长回文子序列

动态规划法

  • dp[i][j] 表示子序列 s[i..j] 中存在的最长回文子序列长度
  • 初始化dp[i][i] = 1
  • 当 s[i] == s[j] 为 true 时,dp[i][j] = dp[i+1][j - 1] + 2
  • 当 s[i] == s[j] 为 false 时,dp[i][j] = max(dp[i+1][j], dp[i][j - 1])
# 求得最长回文子序列的长度
def solution(s):
  l = len(s)
  dp = [[0] * l for i in range(l)]
  for i in range(l):
    dp[i][i] = 1
  # 枚举子串的长度
  for k in range(2, l+1):
    # 枚举子串的起始位置
    for i in range(0, l-k+1):
      j = i + k - 1
      if s[i] == s[j]:
        dp[i][j] = dp[i + 1][j - 1] + 2
      else:
        dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])
  return dp[0][l-1]

时间复杂度为 O(n^2), 空间复杂度为 O(n^2)

总结

以上所述是小编给大家介绍的Python实现常见的回文字符串算法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
python动态监控日志内容的示例
Feb 16 Python
python对数组进行反转的方法
May 20 Python
tensorflow构建BP神经网络的方法
Mar 12 Python
Django Rest framework频率原理与限制
Jul 26 Python
利用Python复制文件的9种方法总结
Sep 02 Python
python使用 request 发送表单数据操作示例
Sep 25 Python
python识别验证码图片实例详解
Feb 17 Python
Python小白垃圾回收机制入门
Jun 09 Python
Python函数的迭代器与生成器的示例代码
Jun 18 Python
pytorch 查看cuda 版本方式
Jun 23 Python
scrapy实践之翻页爬取的实现
Jan 05 Python
Python之qq自动发消息的示例代码
Feb 18 Python
Python 单元测试(unittest)的使用小结
Nov 14 #Python
python for循环输入一个矩阵的实例
Nov 14 #Python
python获取中文字符串长度的方法
Nov 14 #Python
对python插入数据库和生成插入sql的示例讲解
Nov 14 #Python
python正向最大匹配分词和逆向最大匹配分词的实例
Nov 14 #Python
对python中的乘法dot和对应分量相乘multiply详解
Nov 14 #Python
在python中实现对list求和及求积
Nov 14 #Python
You might like
PNGHandler-借助JS让PNG图在IE下实现透明(包括背景图)
2007/08/31 Javascript
JS获取dom 对象 ajax操作 读写cookie函数
2009/11/18 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
BootStrap制作导航条实例代码
2016/05/06 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
2016/11/18 Javascript
Angular.js中上传指令ng-upload的基本使用教程
2017/07/30 Javascript
最通俗易懂的javascript变量提升详解
2017/08/05 Javascript
Vue.js实现分页查询功能
2020/11/15 Javascript
微信小程序动态生成二维码的实现代码
2018/07/25 Javascript
js实现盒子移动动画效果
2020/08/09 Javascript
详解Vue数据驱动原理
2020/11/17 Javascript
go和python调用其它程序并得到程序输出
2014/02/10 Python
python通过floor函数舍弃小数位的方法
2015/03/17 Python
Python使用matplotlib绘制动画的方法
2015/05/20 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
Django实现组合搜索的方法示例
2018/01/23 Python
pycharm重置设置,恢复默认设置的方法
2018/10/22 Python
python的concat等多种用法详解
2018/11/28 Python
Flask框架学习笔记之路由和反向路由详解【图文与实例】
2019/08/12 Python
Python facenet进行人脸识别测试过程解析
2019/08/16 Python
pyhton中__pycache__文件夹的产生与作用详解
2019/11/24 Python
keras模型可视化,层可视化及kernel可视化实例
2020/01/24 Python
python json load json 数据后出现乱序的解决方案
2020/02/27 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
配置H5的滚动条样式的示例代码
2018/03/09 HTML / CSS
德国拖鞋网站:German Slippers
2019/11/08 全球购物
blueseventy官网:铁人三项和比赛泳衣
2021/02/06 全球购物
杭州SQL浙江浙大网新恩普软件有限公司
2013/07/27 面试题
介绍一下Java中的static关键字
2012/05/12 面试题
报告会主持词
2014/04/02 职场文书
校园主题婚礼活动策划方案
2014/09/15 职场文书
2014银行领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
2014年实习生工作总结
2014/11/27 职场文书
创业计划书之书店
2019/09/10 职场文书
Go语言使用select{}阻塞main函数介绍
2021/04/25 Golang
Redis源码阅读:Redis字符串SDS详解
2021/07/15 Redis