码迷,mamicode.com
首页 > 其他好文 > 详细

Hiho-最长回文

时间:2015-04-03 17:31:50      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:最长回文   manacher   

先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”

提示一 提示二 提示三 提示四
样例输入
3
abababa
aaaabaa
acacdas
样例输出
7
5
3


#include<iostream>
#include<string>
using namespace std;
int getMaxSym(string str)
{
	int maxlength = 0;
	int len = str.length();
	int ptag = 0;
	while(ptag < len)
	{
		int left = ptag - 1;
		int right = ptag + 1;
		int oddlenght = 1;
		while(left >= 0 && right < len && str[left] == str[right])
		{
			left--;
			right++;
			oddlenght += 2;
		}
		if(oddlenght > maxlength)
		{
			maxlength = oddlenght;
		}
		//偶数子字符串
		left = ptag;
		right = ptag + 1;
		int evenlength = 0;
		while(left >= 0 && right < len && str[left] == str[right])
		{
			left--;
			right++;
			evenlength += 2;
		}
		if(evenlength > maxlength)
		{
			maxlength = evenlength;
		}

		ptag++;
	}
	return maxlength;
}
int main()
{
	int k = 0;
	cin>>k;
	if(k == 0)
	{
		return 0;
	}
	for(int i = 0; i < k; i++)
	{
		string src;
		cin>>src;
		cout<<getMaxSym(src);
	}
	return 0;
}
上面的方法就是利用遍历中心点,然后向两边进行扩展,然后进行匹配的方法,但是这种方法还是很费时间

在算法中有一种称为Manacher的算法,很好的利用了之前计算出来的最长回文的结果进行判断:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;

char * pre(const char *str)
{
	int length = strlen(str);
	char *prestr = new char[2*length + 4];
	prestr[1] = '$';
	for(int i=0;i<length;i++)
	{
		prestr[2*(i+1)] = '#';
		prestr[2*(i+1)+1] = str[i];
	}
	prestr[2*length+2]='#';
	prestr[2*length+3]='\0';
	return prestr;
}
int getMaxSym(const char *str)
{
    if(NULL == str)
    {
        return 0;
    }
	char *prestr = pre(str);
	int mx =0, pi=1;//边界和对称中心
	int len = strlen(prestr);
	//辅助数组
	int *p = new int[len];
	p[0] = 0;
	for(int i=1;i<len;i++)
	{
		if(mx>i)
		{
			p[i]=min(mx-i,p[2*pi-i]);//核心
		}
		else
		{
			p[i]=1;
		}
		while(prestr[i-p[i]]==prestr[i+p[i]]&&i-p[i]>0&&i+p[i]<len)
		{
			p[i]++;
		}
		if(i+p[i] > mx)
		{
			mx = p[i] + i;
			pi = i;
		}
	}
	//最大回文字符串长度
	int maxlen = 0;
	for(int i=0;i<len;i++)
	{
		if(p[i]>maxlen)
		{
			maxlen = p[i];
		}
	}
	delete []prestr;
	delete []p;
	return maxlen - 1;
}
int main()
{
	int k = 0;
	cin>>k;
	if(k == 0)
	{
		return 0;
	}
	for(int i = 0; i < k; i++)
	{
		string src;
		cin>>src;
		int result = getMaxSym(src.c_str());
		cout<<result<<endl;
	}
	return 0;
}

相关的解释有:

http://blog.csdn.net/ggggiqnypgjg/article/details/6645824

之所以在原始字符串中加入一些特殊字符串是因为我们希望处理出来的回文我们希望都是奇数的

在上面的代码中

mx 表示之前处理的最长回文的最右端标记, p[i] 表示之前获得的最长回文的最长半径




技术分享


技术分享

Hiho-最长回文

标签:最长回文   manacher   

原文地址:http://blog.csdn.net/xietingcandice/article/details/44834351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!