博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Manacher算法笔记 C++
阅读量:7181 次
发布时间:2019-06-29

本文共 1847 字,大约阅读时间需要 6 分钟。

Manacher算法简介:

1.作用:Manacher算法又名马拉车算法,用来求一个字符串中最长回文子串的长度。

2.复杂度分析:时间复杂度为O(n)。

算法核心思想:

1.伪代码:假设str为待判断的字符串,len[ i ]数组存放以该 str[ i ] 字符为中心的最长回文子串的长度,mid为当前最长回文子串的中点,mx为当前最长回文子串的右边界,那么对当前位置 i 有如下伪代码:(此时以知道前 i - 1个字符中最长回文子串的长度以及以每个字符为中心的最长回文串的长度)

  1. 若 i < mx,则 len[ i ] = min ( len[ 2*mid - i ] , mx - i )。
  2. 否则len[ i ] = 1。
  3. 对 i 位置上的字符向两边进行匹配,更新len[ i ]的值,更新结束后更新mid和mx的值。

2.算法思路:为何能按照这样步奏执行算法呢?

2.1 i < mx : 

首先,如果 i < mx,说明字符 str[ i ] 在以mid为中心的回文串中,那么其与以 str[ j ]( i 关于 mid 的对称位置)为中心的最长回文串有关。而以 str[ j ]字符为中心的最长回文串有三种可能:

  • 一种是该串(以j为中心的最长回文串)仍在以mid为中心的最长回文串中
  • 一种是超出
  • 最后一种是刚好相等

我们可以证明第一种与第二种情况下,以 str[ i ] 为中心的最长回文串的长度为len[ j ] 或 mx - i。[ 注释1 ]而第三种情况下,以str[  i ] 为中心的回文串长度却可能大于len[ j ],故需要走伪代码中的第3步来更新len[ i ] 。

2.2 i >= mx :

而如果i >= mx 情况下,说明以 i 为中心的最长回文串无法从之前得到的len[ 1 ~ i -1]中得知,只能先令len[ i ] = 1,再分别向两边拓展,判断回文长度了,故走伪代码中2、3步。

注释1:证明第一、第二中情况下以str[ i ]为中心的最长回文串的长度为len[ j ] 或 mx - i。

  • 若以str[ j ]为中心的最长回文串仍在以str[ mid ]为中心的回文串中,那么由于 i 与 j 关于mid对称,如下图,a != b,而d = a,c = b,故c != d,故len[ i ] = len[ j ]。

  • 若以str[ j ] 为中心的最长回文串超过了以str[ mid ]为中心的最长回文串,同理可证明以str[ i ] 为中心的回文串不可能与以str[ j] 为中心的最长回文串相等。

模板

//Manacher#include
#include
#include
using namespace std;const int MAXN = 1e5;char str[MAXN];char tmp[2*MAXN];int len[2*MAXN];int Manacher(char str[]){ tmp[0] = '$'; tmp[1] = '#'; int str_len = strlen(str); for(int i = 1;i <= str_len;i++){ tmp[2*i] = str[i-1]; tmp[2*i+1] = '#'; } tmp[2*str_len+2] = '\0'; //cout << tmp << endl; int mx = 0; int maxlen = -1; int mid; for(int i = 1; tmp[i]; i++){ if(i < mx) len[i] = min(len[2*mid-i],mx-i); else len[i] = 1; while(tmp[i-len[i]] == tmp[i+len[i]]) len[i]++; if(len[i]+i > mx){ mx = len[i]+i; mid = i; } maxlen = max(maxlen,len[i]-1); } return maxlen;}int main(){ scanf("%s",str); cout << Manacher(str); return 0;}

 

转载于:https://www.cnblogs.com/long98/p/10352164.html

你可能感兴趣的文章
i++为什么是线程不安全的
查看>>
C# log4net 不输出日志
查看>>
最好的年龄减肥
查看>>
2015第43周一solr相关概念
查看>>
大数模板
查看>>
SqlServer时间戳与普通格式的转换
查看>>
转:关于腾讯bugly崩溃的android so符号表使用
查看>>
集成支付宝后出现LaunchServices: ERROR: There is no registered handler for URL scheme alipay
查看>>
Http和Socket详解
查看>>
iOS 多线程开发之OperationQueue(二)NSOperation VS GCD
查看>>
LeetCode - Trapping Rain Water
查看>>
Codeforces 437C The Child and Toy(贪心)
查看>>
蓝桥杯 大臣的旅费
查看>>
hql中不能写count(1)能够写count(a.id)
查看>>
Atitit。Time base gc 垃圾 资源 收集的原理与设计
查看>>
还是态度问题
查看>>
判断记录是否存在的通用方法
查看>>
sift算法c语言实现
查看>>
报表中的Excel操作之Aspose.Cells(Excel模板)
查看>>
(二)STM32中中断优先级理解
查看>>