目前,此问题最好的解法是Manacher算法,时间复杂度为O(n),本文还给出了另外两种便于理解的方法。
1.Manacher算法
//Manacher's ALGORITHM: O(n)时间求字符串的最长回文子串 #include <iostream> #include <algorithm> using namespace std; int Manacher(const string &data, const int &num) { int len=num*2+1;//如:*1*2*3* string str(len,'*'); for(int i=0;i<num;++i) str[2*i+1]=data[i]; int *p=new int[len](); int mx = 0, id = 0;//mx表示0~(i-1)元素的最远右端;id表示具有最远右端中心元素点 for (int i = 1; i<len; ++i) { p[i] = mx > i ? min(p[2*id-i], mx-i+1) : 1; while (str[i + p[i]] == str[i - p[i]]) p[i]++; if (i + p[i] > mx) { mx = i + p[i]-1; id = i; } } int res=*max_element(p,p+len); delete p; return res-1; } int main() { string str="12321476789987678998"; int length=str.size(); cout<<str<<" 的最长回文长度为:"<<Manacher(str,length)<<endl; }
2.暴力法(用到Manacher算法)思想
/*通过插入*来求最大回文长度,此时,最大回文长度为回文半径-1*/ #include <iostream> #include <algorithm> using namespace std; int Manacher(const string &data, const int &num) { int len=num*2+1;//如:*1*2*3* string str(len,'*'); for(int i=0;i<num;i++) str[2*i+1]=data[i]; int max_r=0;//记录最大半径 for (int i = 1; i<len-1; ++i) { int r=0; while ((i - r >= 0)&&(i + r <= len-1)&&(str[i + r] == str[i - r])) r++; if(r>max_r) max_r=r; } return max_r-1;//回文半径减一就是回文长度 } int main() { string str="1232141267997621"; int length=str.size(); cout<<str<<" 的最长回文长度为:"<<Manacher(str,length)<<endl; }
3.用递归实现,复杂度渣到极限O(n*2^n)
/*用递归实现求最长回文长度,复杂度O(n*2^n)*/ #include <iostream> using namespace std; bool is_hw(char *start,char *end) { while(start<end) if(*start!=*end) return false; else ++start,--end; return true; } int urec_(char *start,char *end) { if(start==end) return 1; else if(start<end) { if(is_hw(start,end)) return end-start+1; else return max(rec_(start+1,end),rec_(start,end-1)); } } int main() { string str="123214126798797621"; int length=str.size(); cout<<str<<" 的最长回文长度为:"<<rec_(&str[0],&str[0]+length)<<endl; }
求字符串中的回文最大长度
最新推荐文章于 2023-01-03 22:19:37 发布