manacher

manacher

馬拉車算法說白了就是遞推進行優化求迴文串的算法
就是求p數組,表示以以i爲中心的最長迴文串的半徑
核心就是mx和id的使用

主要分爲三個部分
1.要求的i在mx內部

  		.以i的對稱點爲中心的迴文串完全包含在以id爲中心的迴文串中 
 			p[i]=p[2*id-i];
 		.超出了id爲中心的迴文串邊界 
 			p[i]=mx-i+1; 

2.i在以id爲中心的迴文串之外

	p[i]=1;

當然這樣求得的p[i]可能不是最大的,再來一個while看能不能加長就好了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
const int maxn=110000;
int p[maxn*2+5];//p數組記錄的是以i爲中心的迴文串的半徑,包括i那一位置。
string s,s_new;

void Init()
{
	
	fill(p,p+maxn,0);
}

int Getnew()
{
	int len=s.size();
	s_new="$#";//這裏要從下標是1的位置開始,以防數組越界 
	for(int i=0;i<len;i++)
	{
		s_new+=(s[i]);
		s_new+="#";
	}	
}

int Manacher(){
	Getnew();
	int len=s_new.size();
	
	int mx=1,id=1;//右邊界最大的迴文串的中心點id和邊界 
	int maxlen=1;//記錄最長迴文串的長度 
	
	for(int i=1;i<len;i++)
	{
		if(i<=mx)//i在右邊界之內 
		{
			if(mx-i+1>=p[2*id-i]) //以i的對稱點爲中心的迴文串完全包含在以id爲中心的迴文串中 
			{
				p[i]=p[2*id-i];
			}
			else//超出了id爲中心的迴文串邊界 
			{
				p[i]=mx-i+1;
			}			
			
		}
		else//i在以id爲中心的迴文串之外 
		{
			p[i]=1;
		}
		
		
		while(s_new[i-p[i]]==s_new[i+p[i]]) 
		{
			++p[i];
		}
				
		if(mx<i+p[i]-1) 
		{
			mx=i+p[i]-1;
			id=i;
		}
		
		maxlen=max(maxlen,p[i]);		
		
	}		
	return maxlen-1;
	
}
int main()
{
		cout<<s<<endl;
		int k=Manacher();
		cout<<k<<endl;	
}
發佈了52 篇原創文章 · 獲贊 41 · 訪問量 7245
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章