求字符串中的迴文最大長度

目前,此問題最好的解法是Manacher算法,時間複雜度爲O(n),本文還給出了另外兩種便於理解的方法。

1.Manacher算法

//Manacher's ALGORITHM: O(n)時間求字符串的最長迴文子串 
#include <iostream>
#include <algorithm>
using namespace std;

int Manacher(const string &data, const int &num)
{
	int len=num*2+1;//如:*1*2*3*
	string str(len,'*');
	for(int i=0;i<num;++i)
		str[2*i+1]=data[i];
	int *p=new int[len]();
	int mx = 0, id = 0;//mx表示0~(i-1)元素的最遠右端;id表示具有最遠右端中心元素點 
	for (int i = 1; i<len; ++i)
	{
	    p[i] = mx > i ? min(p[2*id-i], mx-i+1) : 1;
	    while (str[i + p[i]] == str[i - p[i]]) p[i]++;
	    if (i + p[i] > mx) 
		{
	        mx = i + p[i]-1;
	        id = i;
	    }
	}
	int res=*max_element(p,p+len);
	delete p;	
	return res-1;
}

int main()
{
	string str="12321476789987678998";
	int length=str.size();
	cout<<str<<" 的最長迴文長度爲:"<<Manacher(str,length)<<endl; 
}

2.暴力法(用到Manacher算法)思想

/*通過插入*來求最大回文長度,此時,最大回文長度爲迴文半徑-1*/
#include <iostream>
#include <algorithm>
using namespace std;

int Manacher(const string &data, const int &num)
{
	int len=num*2+1;//如:*1*2*3*
	string str(len,'*');
	for(int i=0;i<num;i++)
		str[2*i+1]=data[i];
	int max_r=0;//記錄最大半徑 
	for (int i = 1; i<len-1; ++i)
	{ 
		int r=0; 
	    while ((i - r >= 0)&&(i + r <= len-1)&&(str[i + r] == str[i - r])) 
			r++;
	    if(r>max_r) max_r=r;
	} 	
	return max_r-1;//迴文半徑減一就是迴文長度 
}

int main()
{
	string str="1232141267997621";
	int length=str.size();
	cout<<str<<" 的最長迴文長度爲:"<<Manacher(str,length)<<endl; 
}

3.用遞歸實現,複雜度渣到極限O(n*2^n)

/*用遞歸實現求最長迴文長度,複雜度O(n*2^n)*/
#include <iostream>
using namespace std;
bool is_hw(char *start,char *end)
{
	while(start<end)
		if(*start!=*end) return false;
		else ++start,--end;
	return true;
} 
int urec_(char *start,char *end) 
{
	if(start==end) return 1;
	else if(start<end)
	{
		if(is_hw(start,end)) return end-start+1;
		else return max(rec_(start+1,end),rec_(start,end-1));
	} 
}

int main()
{
	string str="123214126798797621";
	int length=str.size();
	cout<<str<<" 的最長迴文長度爲:"<<rec_(&str[0],&str[0]+length)<<endl; 
}
發佈了37 篇原創文章 · 獲贊 17 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章