leetcode -- manacher算法(c语言实现)

manacher算法是用来处理最大回文子串的算法,时间复杂度为O(n);上一篇文章说的中心扩展算法时间复杂度为O(n^2),遍历O(n),对每个元素都中心扩展时间复杂度O(n)。

关于manacher算法的原理可以参考(也是我今天找的比较好的资料):
湘潭大学2019年ACM集训专题-manacher&回文树
这个看完manacher就好了,大概二十来分钟,看两遍。

[译+改]最长回文子串(Longest Palindromic Substring) Part II

Manacher算法的详细讲解

manacher算法核心就是利用回文字符串自身的性质减少字符的中心扩展次数,同时利用加’#'字符可以避免奇偶分类讨论,回文数的处理上 中心扩展法是必不可少的,也是学习manacher的前提。

char * longestPalindrome(char * s)
{
	int i_mirror = 0, diff = 0, maxlen = 0, centerIndex = 0, C = 0, R = 0;
	
	// 预处理过程    加'#'
	char t[2048];
	int p[1024];
	unsigned int i = 0, j = 1;
	t[0] = '#';
	for (; i < strlen(s); i++, j++)
	{
		t[j++] = s[i];
		t[j] = '#';
	}
	t[j] = '\0';
	// 预处理结束

	for (i = 0; i < strlen(t); i++)
	{
		i_mirror = 2*C - i;				// 确定i关于C的镜像
		diff = R - i;

		if (diff >= 0)		// i 在C与R的中间
		{
			if (p[i_mirror] < diff)		//如果i_mirror的回文半径在L后面
				p[i] = p[i_mirror];
			else
			{
				p[i] = diff;
				while (t[i+p[i]+1] == t[i-p[i]-1])		// 中心扩展法,更新R、更新C
				{
					p[i] ++;
					C = i;
					R = i + p[i];
				}
			}
		}
		else							// 当i在R之和
		{
			p[i] = 0;					// 初始化
			while (t[i+p[i]+1] == t[i-p[i]-1])	// 只能中心扩展
			{
				p[i] ++;
				C = i;
				R = i + p[i];
			}
		}

	}
	// 确定最大长度和中心索引的下标
	for (i = 1; i < strlen(t) - 1; i ++)
	{
		if (p[i] > maxlen)
		{
			maxlen = p[i];
			centerIndex = i;
		}
	}

	s[(centerIndex)/2 -1 + maxlen] = '\0';		// 原地修改字符串

	return s + (centerIndex/2 - 1);				// 返回,碰到'\0'最大回文子串结束

}

注意一下,上述代码直接提交leetcode是有问题的。

Line 37: Char 28: runtime error: index -1 out of bounds for type ‘char [2048]’ (solution.c)

大意就是在

while (t[i+p[i]+1] == t[i-p[i]-1])

出现了t[-1]这个情况。但是我用sublime配置c环境运行没出现这个问题,用printf打印调试也没问题。用win10 + codeblocks的13.12版本运行也没问题,准备用codeblocks单步调试的,但是试了好几次,还没调试完,电脑风扇就转得飞起,codeblocks也出现未响应,遂放弃;但是在debug过程中,发现 i-p[i]-1 的值没问题。

测试结果如下图:
leetcode -- manacher算法(c语言实现)_第1张图片

你可能感兴趣的:(算法)