最长回文子串
来源:互联网 发布:济南行知小学学区划分 编辑:程序博客网 时间:2024/05/22 06:10
最高效的方法是Manacher算法,时间复杂度为O(N),在2N步内即可找到最长回文子串
Manacher算法的基本思想是用一个O(N)的数组P来存储每一个元素为中心时回文子串的长度
为了提高效率,还特别增加了两种措施:
1.对原字符串的首尾以及每个元素间都增加一个特殊字符(如#),使得新字符串的长度都变成奇数位
2.计算P[i]时会考虑到之前计算过的回文长度,设i之前最长回文子串位置为curcenter,则对应的回文子串长度为P[curcenter],右边界即为right=curcenter+P[curcenter]。根据i和right的关系,有三种情况:
(1) i>=right,说明当前元素i超出了curcenter的回文串范围,此时需要重新计算i的回文串长度,并把curcenter置为i
(2) i<right,且i相对于curcenter的对称点i'的子串长度为P[i'],i+P[i']也不超过right,说明i的子串仍然在right范围内,此时P[i]=P[i'],不需要计算
(3) i<right,但i+P[i']超过了right,说明i的子串超出了right范围,此时P[i]至少等于[i,right]区间的长度,right以外的回文串长度需要额外计算
代码:
#include <iostream>#include <string>using namespace std;int findMaxDasLen( const string& str , int& center , int& sublen ){//计算str的最长回文子串长度并返回int len = str.length();if( len <= 1 )return len;string newstr;for( string::const_iterator it=str.begin() ; it!=str.end() ; it++ ){//每个字符间加上#newstr += "#";newstr += (*it);}newstr += '#';int newLen = newstr.length();//加完#后的字符串长度int* P = new int[ newLen ];//用来存储以每个元素为中心的最长回文串长度P[0] = 1;//第一个字符是#,最大回文长度为1int curcenter = 0;//初始中心位置是0for( int pos=1 ; pos<newLen ; pos++ ){int right = curcenter + P[curcenter];//右边界坐标int lpos = 2*curcenter-pos;//左对称点坐标if( pos>=right )P[pos] = 1;//pos在右边界外,需要从头计算回文串长度else if( P[lpos] <= right-pos )P[pos] = P[lpos];//pos的回文串全在right以左elseP[pos] = right-pos;//pos的回文串部分在right以左while( pos+P[pos]<newLen && pos-P[pos]>=0 && newstr[pos+P[pos]]==newstr[pos-P[pos]] )P[pos]++;//检查pos为中心的回文串if( pos + P[pos] > right )curcenter = pos;//回文串超过右边界,更新中心位置}int maxpos=0;for( int i=1 ; i<newLen ; i++ ){if( P[i] > P[maxpos] )maxpos = i;}sublen = P[maxpos]-1;//原字符串中的最大回文串长度center = (maxpos)/2;//原字符串中的最大回文串中心坐标delete[] P;return sublen;}int main(){string str1 = "abaaba";string str2 = "aaaabaa";string str3 = "acacdas";int center=0;int sublen=0;cout << findMaxDasLen( str1 , center , sublen ) << endl;cout << str1.substr( center-(sublen)/2 , sublen ) << endl;cout << findMaxDasLen( str2 , center , sublen ) << endl;cout << str2.substr( center-(sublen)/2 , sublen ) << endl;cout << findMaxDasLen( str3 , center , sublen ) << endl;cout << str3.substr( center-(sublen)/2 , sublen ) << endl;system("pause");}
0 0
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- Mybatis配置文件分析
- spring与mybatis三种整合方法
- Spring MVC 框架搭建及详解
- MyBatis+Spring 基于接口编程的原理分析
- Volley.jar 制作方法
- 最长回文子串
- DirectX 9.0c游戏开发手记之“龙书”第二版学习笔记之7: Chap9: Color
- Reverse words
- 算法学习之排序算法:插入排序(直接插入排序、折半插入排序、2-路插入排序)
- 关于编程学习的七点思索
- 各种开源协议介绍 BSD、Apache Licence、GPL V2 、GPL V3 、LGPL、MIT
- 8种Nosql数据库系统对比
- 算法学习之排序算法:冒泡排序
- Redhat-linux常识