https://leetcode-cn.com/problems/longest-palindromic-substring/
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
四种算法:
一、暴力法
双指针双重循环切分字符串,双指针查找对比。
时间复杂度O(n^3)
char* longestPalindrome(char* s) {
int length = strlen(s),l =0,r = length-1,index1=0,index2=0,max = 0,n = 0,flag=1;
char *p=NULL;
if(length<=1) return s;
for(int i = 0;imax){
max = n;
index1 = i;
index2 = j;
}
}
}
}
p = (char*)malloc(sizeof(char)*(index2-index1+2));//复制回文串
for(int i = index1;i<= index2;i++){
p[i-index1] = s[i];
}
p[index2-index1+1] ='\0';
return p;
}//时间复杂度O(n^3)空间复杂度O(1)
二、中心拓展算法
n个字符串有2*n-1个回文中心,比如abbab,对于单个字符,中心是它本身,如a,对于双字符,中心是空,如bb。
只要从中心向两端匹配,就能匹配出当前回文串的长度。
int expand(char *s,int left,int right,int length);
char* longestPalindrome(char* s) {
int length=strlen(s),l=0,r=0;
char *p=NULL;
for(int i = 0;i < length;i++){ //最基本的回文单位是单字符或者相同双字符。
int len1 = expand(s,i,i,length); //遍历所有单字符
int len2 = expand(s,i,i+1,length); //遍历所有连续双字符
int len = len1 > len2 ? len1 : len2;
if(len > r - l){ //这句话等于(len>=r-l+1)而r-l+1为同样长的字符串
l = i - (len-1)/2; //根据中点值,计算左右界限
r = i + len/2;
}
}
p = (char *)malloc(r-l+2); //复制数组
for(int i = l;i<=r;i++){
p[i-l]=s[i];
}
p[r-l+1] = '\0';
return p;
}
int expand(char *s,int left,int right,int length){ //拓展函数,返回长度
int l = left,r = right;
while(l>=0 && r
三、动态规划
设置辅助数组dp[length][length],以若从起始点为i,结束点为j,且i,j范围内的字符串是回文,那么dp[i][j]=1。
边界条件,dp[i][i] = 1,dp[i][i+1] = dp[i] == dp[i+1].
状态转移方程:dp[i][j] = dp[i+1][j-1] && dp[i]==dp[j];
char* longestPalindrome(char* s) {
int length = strlen(s),max = 0,index1=0,index2=0;
char **p=NULL,*p1=NULL;
p = (char **) malloc(sizeof(char*)*length);
for(int i = 0;i
四、Manacher算法
请自行阅读相关文献
char* longestPalindrome(char* s) {
int length = strlen(s),*len=NULL;
int mid=1,mx=0,max_mid=0,max = 0;
char *p=NULL,*p2=NULL;
if(length==0) return s;
p = (char *)malloc(length+length+3);
p[0] = '$';
p[1] = '#';
for(int i=0,j=2;imx){ //若新的右界大于当前右界,则重置中点,重置右界
mx = i+len[i];
mid = i;
}
if(len[i]>max){ //记录最长串中点和半径
max = len[i];
max_mid = i;
}
}
p2 = (char *)malloc(max+2); //将回文串复制到新的数组。
for(int i = max_mid - max +2,j=0;i<=max_mid+max-2;i++){
if(p[i]=='#') continue;
else{
p2[j++] = p[i];
}
if(i==max_mid+max-2) p2[j]='\0';
}
return p2; //返回
}//时间复杂度O(n) 空间复杂度O(n)