zoukankan      html  css  js  c++  java
  • manacher算法解析

    manacher是很简单的字符串回文算法,作用是O(n)求出一个字符串的最长回文子串

    下面给出这一算法的详解

    首先,我们设原字符串是aaabba,很显然,这个字符串最长的回文子串长度为4

    那么我们就要思考一种算法来计算出这个长度

    于是manacher横空出世

    首先,我们知道,一个回文子串一定有一个对称轴(或者你叫对称中心?),所以正常来讲,如果想O(n)求出最长回文子串,我们只需枚举每个对称轴,然后O(1)递推即可

    可是现在就产生了一个问题:如果原字符串是上面说的那样,那...对称轴是在ab中间的啊,这怎么找出来啊

    所以manacher需要一个操作,即在所有中间的位置插入一个'#'之类的无用字符,这样我们就可以忽略掉对称轴在两个字符中间的情况,只考虑对称轴落在字符上的情况即可

    所以我们记p[i]表示以i为回文中心,回文半径为p[i]

    然后我们考虑递推

    怎么推?

    我们记录一个maxp,表示在i之前所有的回文中心中,回文右端点最远在哪,记p0表示这个最远的右端点所对应的回文中心

     看蒙了?举个例子:

    (图中黑线表示字符串,p0为回文中心,maxp为回文右端点)

    接下来,我们考虑如何用这个东西维护p[i]

    这是需要分类讨论的,即:

    ①:

    若i<maxp,有:

    p[i]=min(p[2*p0-i],p[p0]+p0-i);

    这一点是显而易见的:如果i<maxp,那么我们显然可以找出一个j,使j与i关于p0对称,于是j=2*p0-i

    而根据对称性,j周围的字符一定和i周围的字符相同,所以p[i]可以由p[j]来更新

    如图所示,由于对称性,所以i右侧一部分和j左侧一部分相同,同时i左侧一部分和j右侧一部分相同,同时根据j的对称性,j左右两侧相同,故i左右两侧相同,为回文。

    至于另一个也很好理解,就是从i到maxp的一段,假设他整个都能构成回文。这一值和刚才对称求出的一个值取最小值才能保证结果的合理性。

    ②:i>=maxp

    没什么办法,暴力吧..

    接下来谈谈暴力:

    其实无论是情况①还是情况②都需要暴力,因为我们无法保证①求出的是最大值,我们只能保证①求出的是一个可能的合法答案

    所以我们需要暴力从p[i]的已有值开始向下跳,跳到不能跳为止即可

    剩下的就是代码了

    比较好些

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    char a[51000005];
    char s[102000005];
    int p[51000005];
    int maxp,p0,l;
    int ans=1;
    void manacher()
    {
    	for(int i=1;i<l;i++)
    	{
    		if(i<maxp)
    		{
    			int j=(p0<<1)-i;
    			p[i]=min(p[j],p[p0]+p0-i);
    		}else
    		{
    			p[i]=1;
    		}
    		while(s[i-p[i]]==s[i+p[i]])
    		{
    			p[i]++;
    		}
    		if(i+p[i]>maxp)
    		{
    			p0=i;
    			maxp=i+p[i];
    		}
    	}
    }
    int main()
    {
    	scanf("%s",a+1);
    	l=strlen(a+1);
    	p[1]=1;
    	s[0]=s[1]='#';
    	for(int i=1;i<=l;i++)
    	{
    		s[2*i]=a[i];
    		s[2*i+1]='#';
    	}
    	l=(l<<1)+2;
    	s[l]='0';
    	manacher();
    	for(int i=1;i<=l;i++)
    	{
    		ans=max(ans,p[i]-1);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764210.html
Copyright © 2011-2022 走看看