Hiho-最长回文

先从标准输入读取一个整数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] 表示之前获得的最长回文的最长半径

时间: 2024-07-30 18:27:00

Hiho-最长回文的相关文章

[hiho 01]最长回文子串、Manacher算法

题目描述 - 基础方法:枚举子串,判断是否为回文串. - 改进:枚举中间位置,向两侧拓展. - 再改进:利用以前的信息,使得不用每个新位置都从长度1开始拓展. - 优化:将字符串预处理为奇数长度以避免考虑条件分支. - 再优化:开头加入特殊字符避免考虑边界. Manacher 算法: id 是中心点,mx 是其边界.P[i] 表示以 i 为中心的最长回文子串的折半长度. 只要 i < mx, 以 i 为中心的回文子串就可以不必从长度1开始找,而从min{P[j], mx - i}开始(其中j为i

hiho #1032: 最长回文子串

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是1

HiHo 1032 最长回文子串 (Manacher算法求解)

Manacher算法o(n)求解最长回文子串问题 非常巧妙 #include<bits/stdc++.h> using namespace std; char str[2000020],s[2000020]; int p[2000020]; int len,id,mx; void pre() //对字符串进行预处理 { len=strlen(s); str[0]='$'; str[1]='#'; for(int i=0;i<len;i++) { str[i*2+2]=s[i]; str[

hihoCoder hiho一下 第一周 #1032 : 最长回文子串 (特殊处理)

思路: (1)暴力穷举.O(n^3) -----绝对不行. 穷举所有可能的出现子串O(n^2),再判断是否回文O(n).就是O(n*n*n)了. (2)记录位置.O(n^3) -----绝对不行. 先扫一遍,记录每个字符在上一次出现的位置pos.每次考虑第i个字符,如果回文子串包括 i 的话,那么肯定在i的前面有一个跟第i个字符是一样的,利用之前记录的位置pos[i]可以找到与第i个相同的字符,如果i-pos[i]比之前发现的最长的子串max还短,那么不用比较了.如果更前面还有和第i个字符一样的

hiho#1032 : 最长回文子串 (manacher算法O(n)时间求字符串的最长回文子串 )

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一

hiho一下--第一周(最长回文子串)

时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往

hiho一下 第一周 最长回文子串

时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往

hiho一下第一周——最长回文子串

题目连接 http://hihocoder.com/problemset/problem/1032 题目分析 类似于KMP的思想,利用已经匹配的信息计算未匹配的信息. 基本原理就是:我们将f[i]定义为以i为中心的最长回文串长度.那么如果有f[5]=7,f[4]=3, 那么我们可以得到f[6] >=3.以此来减少比较次数.当然还有一些细节要处理.比如回文串长度的奇偶性. 代码 这个是我自己写的版本,不是很精简. #include <iostream> #include <algor

HDU 3068 最长回文 (manacher算法)

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 9188    Accepted Submission(s): 3159 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

最长回文子序列

题目:给你一个字符串,求它的最长回文子序列,比如"bbbab" 最长回文子序列是"bbbb" 所以返回4,,"abab"最长子序列是"aba"或者"bab" 所以返回3 思路:和之前做的几道dp不同,,,也是我不够变通,,打dp表的时候总习惯左上到右下的顺序,但是这个顺序却固化了我的思维,忽略了对于题解本身含义的理解....... 这个题从下到上开始打表,最重要的是它的含义,,,知道dp[i][j]意味着什