浅谈Manacher`s 算法

马拉车算法是让你求出一个串儿中的最长回文字串的算法,他的时间复杂度均摊下来是o(n)的 ,他的主要难点在于如何构建出p数组,下面上代码,看着代码嘬着上面的注释会有更好的效果哦

代码:

马拉车算法是让你求出一个串儿中的最长回文字串的算法,他的时间复杂度均摊下来是o(n)的 ,他的主要难点在于如何构建出p数组,下面上代码,看着代码嘬着上面的注释会有更好的效果哦

代码:

#include <bits/stdc++.h>
int p[100000];//p[i] 表示的是你在第i点位中心的时候向左或向右(也就是半径!半径!) 的距离
int id,mx;//id 表示的是你现在所在的对称中心,mx表示的是在当前对称中心下你可以向右移动的最大位置在哪里 
using namespace std;
int main()
{
	string ch,sh;
	sh = "$#";
	//cin>>ch;
	getline(cin,ch);
	int len = ch.size();
	for(int i = 0 ; i < len ;i++)
	{
		sh+=ch[i];
		sh+="#";
	}
	int id = 0,mx = 0;
	len = sh.size();
	for(int i = 1 ; i < len ; i++)//需要注意的是当我们算到以i为回文串对称点的时候,那么以j(0<=j<i)为对称点的最长回文长度我们已经算出来了
	{
		p[i] = mx>i ? min(p[2*id-1],mx-i):1;     
	     //_____mx`______j______id______i________mx____
	  //                 ______         _____ ① 
	  //         __|_______________    _____________|___ 
	  //对于mx>i的时候有两种情况,一种是i点关于id的对称点J点他的最长回文半径p[j]是小于mx-i的
	  //那么很显然这个时候 p[i] = p[j]的(如情况1,,因为我们知道以id为对称点的最长回文半径是大于i的,
	  //所以可以很清楚的知道,i和j是关于id对称的,那么i的对称长度其实就等于j的对称长度),第二种就是p[j]>mx-i的,那么对于这种情况我们
	  //可以肯定的是,在i到mx的位置我们可以肯定的是他们是回文的,(如情况②在|之前他们肯定都是回文)
	  //那么我们先把这部分给变成p[i]之后超过的部分我们就要去暴力匹配t[p[i] + i] 是不是 等于t[i-p[i]]
		while(sh[p[i] + i] == sh[i-p[i]]) ++p[i];
		if(p[i]+i > mx)
		{
			mx = i+p[i];
			id = i;
		}	
	}
	int ans = 0 ;
	for(int i = 0 ; i < len ; i ++)
	{
		ans = max(ans,p[i]-1);//解释一下这里为什么是p[i]-1,我们知道在我们变换过的串儿中所有的回文串都是奇数,而且p[i]中存的是
							//以i位对称中点时候的半径!半径,那么总长其实就是2*p[i]-1(-1是因为对称中心多算了一次),之后我们可以发现
							//在所有的回文字串儿中,分隔符一定比原来的字符多一个也就是多了p[i]个分隔符,那么还剩下来的原来的字符就是p[i]-1个 
	}
	cout<<ans<<endl;
	 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值