算法练习 - 最长回文字串(Manacher 算法学习)

本文详细介绍了Manacher算法,用于解决找到给定字符串的最长回文子串问题。通过在字符串中插入特殊字符解决回文串长度奇偶性问题,然后通过数组P记录回文子串的中心点长度。文章分析了三种不同情况下的算法实现,并提供了C++代码示例。
摘要由CSDN通过智能技术生成

题目描述

给定一个字符串,求它的最长回文子串的长度。


Manacher算法

这是一个经典的算法问题,近期在网上看了很多人的讲解,感觉仍不是特别清晰,起码看起来还是有些累的。终于在看了一个英文介绍(http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html),又苦苦思索1天后,豁然开朗,所以把自己的学习心得记录下来,以方便以后复习。

首先放上C++的程序实现(代码引自http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html,添加了一些注释,将结尾查找起始点的部分删除),代码十分晦涩,如果不需要知道原理只需要实现方法的朋友,请直接粘贴到你的程序中即可运行。如果希望知道原理,请结合后面的分析阅读。

/**********************************************************
 * Manacher's algorithm should insert special character(#)
 * into original string, then all strings whatever it's 
 * length is odd or even will be extened to even. 
 * And add a specila charactor at the begin and end of the 
 * string to avoid over position limitition. Such as 
 * "abaca" should be change to "^#a#b#a#c#a#$"
 **********************************************************/
string ManacherPreprocess(const string& str)
{
	string s = "^";
	for(string::size_type i = 0; i < str.length(); ++i)
	{
		s+="#";
		s+=str[i];
	}
	s+="#$";

	return s;
}

/**********************************************************
 * find out the longest palindromic substring.
 **********************************************************/
string LongestPalindromeManacher(const string& str)
{
	string T = ManacherPreprocess(str);
		
	int cIndex = 0;	 //index of center of Palindromic substring in T. the substring is the nearest and longest
	int rightEdge = 0;  //right edge index of Palindromic string centers at cIndex.

	// store intermediate result in an array P, 
	// where P[i] equals to the length of the palindrome centers at T[i].
	int N = T.length();
	int *P = new int[N];

	//Length of the longest Palindromic substring
	int maxLen = 0;
	int centerIndexOfMax = 0;

	for(int i = 1; i < N - 1; ++i)
	{
		//mirrorIndex is the mirrored index of i based on cIndex.
		//In fact, this mirrorIndex is only meaningful while i is 
		//in the index range of Palindromic string which center is cIndex.
		//
		//If i is out of range, should calculate Palindromic string 
		//centered in i.
		int mirrorIndex = 2 * cIndex - i; 
		
		//We assume there's a Palindromic string which centers at cIndex.
		P[i] = (rightEdge > i) ? min(rightEdge-i, P[mirrorIndex]) : 0;

		//Try to find out the Palindromic string which center is i
		while(T[i + 1 + P[i]] == T[i - 1 - P[i]])
			P[i]++;

		if((i + P[i]) > rightEdge)
		{
			//Palindromic string centers at cIndex even cannot cover T[i],
			//so cannot conver the right parts. so move cIndex to i and update rightEdge.
			cIndex = i;
			rightEdge = i + P[i];
		}
		
		//Record index of which item in P contains the longest Palindromic substring
		//and the length of the substring.
		//These will be used to find out the real substring from input str. 
		if(maxLen < P[i])
		{
			maxLen = P[i];
			centerIndexOfMax = i;
		}
	}

	/* Original statements which cost extra O(N), so remove    */
	/* Find the maximum element in P.
	/***********************************************************/
	//int maxLen = 0;
	//int centerIndexOfMax = 0;
	//for (int i = 1; i < N-1; i++)
	//{
	//	if (P[i] > maxLen) 
	//	{
	//		maxLen = P[i];
	//		centerIndex = i;
	//	}
	//}

	delete []P;
	return str.substr((centerIndexOfMax - 1 - maxLen)/2, maxLen);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值