最长回文子串
来源:互联网 发布:怎么ping网络通不通 编辑:程序博客网 时间:2024/05/02 01:50
回文串:如果一个字符串正着读和反着读是一样的,那么它就是一个回文串。例如,a,aba,abba,aaaa等都是回文串。
最长回文子串问题是指,给定一个字符串,求出这个字符串中最长的连续的回文子串。
最长回文子串问题容易与最长回文序列问题混淆,最长回文字串是在给定字符串中连续的回文子串,而最长回文序列问题中可以不连续。例如,给定一个字符串abcbdda,这个字符串的最长回文子串是abc或bcb,而最长回文子序列为abba或adda。
最长回文子串解法一:暴力搜索
对于最长回文子串问题,最容易想到的方法也是最简单粗暴的解法就是,遍历字符串所有子串,并确定每一个子串是否为回文串。一个字符串中,它的字串的数量为O(n^2),遍历每个子串需要O(n)的时间,因此,这个解法的时间复杂度为O(n^3)
最长回文字符串解法二:动态规划
可能有很多人像我一样会想到,这是一个动态规划问题。判断动态规划问题的两个显著条件就是:一.原始问题具有最优子结构。二.子问题的解有重叠
首先我们可以将这个问题分解为子问题,即将一个字符串s分解为O(n^2)个子串,然后判断每个子串是否为一个回文串,并找到最长的回文子串。
假如s[i,j]是一个回文串(i-j>=2),那么s[i+1,j-1]一定也是一个回文串,那么对于子问题:判断s[i,j] (i-j>=2)是否是一个回文串,那么我们首先可以判断s[i+1,j-1]是否为一个回文串,1.如果s[i+1,j-1] 是回文串,那么我们接下来可以根据s[i]是否等于s[j]来判断s[i,j]是否为回文串,2.如果s[i+1,j-1]不是回文串,那么s[i,j]一定也不是回文串。以record[i,j]记录s[i,j]是否为回文串,则有:
string longestPalindrome(string s) { int length=s.length(); vector<vector<bool>> record(length,vector<bool>(length,false)); for(int i=0;i<length;++i) record[i][i]=true; for(int l=1;l<length;++l){ //先解决字符串长度为l+1的最优子问题 for(int i=0;i+l<length;++i){ //i是子字符串起始位置 if(s[i]==s[i+l]){ if(l==1) record[i][i+l]=true; else if(record[i+1][i+l-1]==true) record[i][i+l]=true; } } } int start=0; int end=0; int maxLen=0; for(int i=0;i<length;++i) for(int j=i;j<length;++j){ if(record[i][j]==true && j-i+1>maxLen){ start=i; end=j; maxLen=j-i+1; } } return s.substr(start,end-start+1); }
动态规划算法的时间复杂度为O(n^2),空间复杂度为O(n^2)。
那么有没有复杂度更低的算法呢?
最长回文子串解法三:Manacher 算法
Manacher算法讲解的非常详细,时间复杂度为O(n)。
程序如下:
string longestPalindrome(string s){ //Manacher法 int length=s.length(); string pad_s; pad_s.resize(2*length+1); for(int i=length-1;i>=0;--i){ pad_s[2*i+2]='#'; pad_s[2*i+1]=s[i]; } pad_s[0]='*'; //防止在下面的while循环中出界 vector<int> r(2*length+1,0); int center=0; int maxStart=0,maxEnd=0,maxLen=0; for(int i=1;i<2*length+1;++i){ if(center+r[center]>i) r[i]=min(r[center]-(i-center),r[center-(i-center)]); else r[i]=1; while(pad_s[i+r[i]]==pad_s[i-r[i]]) ++r[i]; if(i+r[i]>center+r[center]) center=i; if(r[i]>maxLen){ maxLen=r[i]; maxStart=i-r[i]+1; maxEnd=i+r[i]-1; } } string result; for(int k=maxStart;k<=maxEnd;++k){ if(pad_s[k]!='#') result.push_back(pad_s[k]); } return result; }
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- bootstrap datetimepicker的时间变成1899年
- 小全栈
- Caffe编译安装全记录
- storage system
- MyEclipse+Tomcat+MAVEN+SVN项目完整环境搭建
- 最长回文子串
- 设计模式--架构型设计模式
- 为什么32位机跑linux的用户进程地址是从0x08048000开始呢?
- MyEclipse中不能将WEB项目发布到TOMCAT中解决办法
- Spring+SpringMVC+Hibernate 基本Demo(注解、Maven管理)
- UCenter 基本原理
- history.back()在safari中不重新加载js问题怎么解决
- 关于 golang 并发
- [iBET Malaysia] RM30 Free RM50 Deposit Promotion(Deposit, Free RM50, ibet, ibet malaysia, Promotion)