manacher算法_求最长回文子串长度

时间:2023-03-10 00:22:57
manacher算法_求最长回文子串长度

很好的总结,转自:

http://blog.csdn.net/dyx404514/article/details/42061017

总结为:两大情况,三小情况。

两大情况:I. i <= p

1.要处理的位置i及i为中心的回文半径Len[i] < p-i已经完全包含在某个回文中了,这种情况不用计算,len[i] = len[j]。

2.要处理的位置i在某个回文中,但是以i为中心的回文半径len[i] >= p-i,需要往后匹配,重新更新p,及对应的po和Len[i];

II. i > p

要计算的位置已经超出某个回文了,之前的回文已经没用,要重新计算新的位置了。只能挨个匹配了。

 // manacher.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
using namespace std; string ManaStr(string &orgStr,int length)
{//构造“马拉车”串
if(length == )
return NULL; string manacherString(*length+,'#');
for(int i = ;i < length;i++)
manacherString[*i+] = orgStr[i]; cout<<manacherString<<endl;
return manacherString;
} int manacher(string &manStr,int manacherLen)
{//“马拉车”计算过程,主要是每个位置对应的回文半径数组的生成,pArr[i]
if(manacherLen == )
return ; int Len[];//回文半径数组
for(int i = ; i <;i++)
Len[i] = ;
for(int i = ; i <;i++)
cout<<Len[i];
int po = ;//某个回文中心
int mostRight = -;//某个回文串最右的位置,并不包含这个位置
int result = ; //for(int i = 0;i != manacherLen;i++)
for(int i = ;i != ;i++)
{
Len[i] = mostRight > i ? min(mostRight-i,Len[*po-i]):;
/*
当前位置i包含在某个回文串中,那么Len[i]的值就是i到mostRight或者
关于po对称的j位置的Len值(j = 2*po-i)
*/
while(i+Len[i] < manacherLen && i-Len[i] >=)
{
if(manStr[i - Len[i]] == manStr[i + Len[i]])
Len[i]++;//检查是否可扩
else
break;
}
if(i+Len[i] > mostRight)
{//扩到mostRight之外了,旧的回文串就不起作用了,更新成新的回文串
//mostRight = Len[i] + 1;!!!!!!艹!!!会死人啊
mostRight = Len[i] + i;
po = i;
}
result = max(result,Len[i]);
}
return result - ;
} int _tmain(int argc, _TCHAR* argv[])
{
string originalString = "abc1234321ab";//结果应该为7
int originalLen = originalString.length();
//int originalLen = 12;
cout<<originalString<<endl;
string manacherString = ManaStr(originalString,originalLen);
int manStrLen = *originalLen + ;
cout<<"原串中包含的最长回文长度为:"<<manacher(manacherString,manStrLen)<<endl;
system("pause");
return ;
}

manacher

一个变形题

 // manacher_.cpp : 定义控制台应用程序的入口点。
//题目:给定一个串,求 在串的后边添加最小字符使得整体都是回文
//解法:利用manacher算法,当mostRight == length的时候停止,并记录下Len[i]
// 找到包含最后一个字符的回文串,之前的逆序就是要求的结果
//例子:abcd123321,在后边加dcba就是回文,返回dcba。 #include "stdafx.h"
#include <iostream>
#include <string>
using namespace std; string manStr(string &orgStr,int orgLen)
{
if(orgLen == )
return NULL; string manaString(*orgLen+,'#');
//string的一种构造方法string(num,ele)
for(int i = ; i < orgLen; i++)
manaString[*i+] = orgStr[i]; cout<<manaString<<endl;
return manaString;
} void manacherCore(string& mancherStr,int manaLen)
{
if(manaLen == )
return; int mostEnd = ;
int mostRight = -;
int po = ;
int Len[];
for(int i = ; i< ; i++)
Len[i] = ;//初始化Len for(int i = ;i != manaLen; i++)
{
Len[i] = mostRight > i? min(mostRight - i,Len[*po-i]):;
//while(i+Len[i] < manaLen && i- manaLen > -1)麻痹又写错
while(i+Len[i] < manaLen && i- Len[i] > -)
{
if(mancherStr[i + Len[i]] == mancherStr[i - Len[i]])
Len[i]++;
else
break;
}
if(i + Len[i] > mostRight)
{
mostRight =i + Len[i];
po = i;
}
if(mostRight == manaLen)
{
mostEnd = Len[i];
break;
}
}
//string result(10-(mostEnd-1),'0');//保存结果的string
string result(-mostEnd+,'');//这里应该是原串长度10
int resLen = result.length(); for (int i = ; i < resLen; i++)
result[resLen-i-] = mancherStr[*i+];
cout<<result<<endl; } int _tmain(int argc, _TCHAR* argv[])
{
string orginalStr = "abcd123321";
cout<<orginalStr<<endl;
int orgLen = orginalStr.length();
string mancherStr = manStr(orginalStr,orgLen);
int manaLen = mancherStr.length();
manacherCore(mancherStr,manaLen);
system("pause");
return ;
}

manacher变形