一起刷LeetCode5-Longest Palindromic Substring

 发现自己原来掌握的一下算法,都忘掉了,啊啊啊

------------------------------------------------------------------------------------------------------

Longest Palindromic Substring

Given a string S, find the longest palindromic substring in S.

You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

【题意】:给你一个字符串,求最长回文字符子串。

【心路历程】:这题一开始我就照着O(n)的方法想,一开始是想扫描一遍字符串,然后递增的处理奇数回文串和偶数回文串的情况。

但是发现对于既可以是奇数回文串也可以是偶数回文串的情况处理不了,比如“aaaa”,“aaa”。于是感觉到自己想歪了。

这题有个O(n)的方法,但是没看懂。。。

一般的方法是O(n*2),有两个大的思路:

一个是枚举回文串中心的位置,然后不断地向两边递增。直到不满足回文串的要求。

一个是动态规划的思想,dp[i][j]表示从i到j字符串是不是回文串,有两个值True ,False。动态转移方程为:

dp[i][j] = ( dp[i+1][j-1] && s[i] == s[j] ).

其实还可以将字符串反转一下,然后求最长连续公共子串。(其实这个是以前我处理最长回文子串常用的方法,但是这次做题已经忘得一干二净了)

动态转移方程为: dp[i][j] = max(  dp[i-1][j-1] + (s[i] == s[j]),   dp[i-1][j],   dp[i][j-1]  )

-------------------------------------------------------------------------------------------------------------------------------------------

代码如下:

首先是枚举回文串中心的位置的代码:

 1 struct node {
 2     int l;
 3     int r;
 4 };
 5 struct node  f(char * s,int l,int r,int len) {
 6     struct node a; 7 while(l >= 0 && l < len && r >= 0 && r < len && s[l] == s[r]) { 8 l--; 9 r++; 10  } 11 a.l = l + 1; 12 a.r = r - 1; 13 return a; 14 } 15 16 char* longestPalindrome(char* s) { 17 int i,len,l,max = 0; 18 len = strlen(s); 19 char * ans = (char *)malloc(1000*sizeof(char)); 20 struct node p; 21 int maxr,maxl; 22 for(i = 0; i < len; i++) { 23 p = f(s,i,i,len); 24 l = (p.r - p.l + 1); 25 if(l > max) { 26 max = l; 27 maxr = p.r; 28 maxl = p.l; 29  } 30 if(i + 1 < len && s[i] == s[i + 1]) { 31 p = f(s,i,i+1,len); 32 l = (p.r - p.l + 1); 33 if(l > max) { 34 max = l; 35 maxr = p.r; 36 maxl = p.l; 37  } 38  } 39  } 40 for(i = 0; i < maxr - maxl + 1; i++) { 41 ans[i] = s[maxl + i]; 42  } 43 ans[i] = '\0'; 44 return ans; 45 }

然后是dp的代码:

 1 char* longestPalindrome(char* s) {
 2     int dp[1001][1001];
 3     int max = 1,start = 0;
 4     char * ans = (char*)malloc(1000*sizeof(char));
 5     memset(dp,0,sizeof(dp));
 6     int len = strlen(s),i,j; 7 for(i = 0; i < len; i++) { 8 dp[i][i] = 1; 9  } 10 for(i = 0; i < len; i++) { 11 if(i + 1 < len && s[i] == s[i + 1]) { 12 dp[i][i+1] = 1; 13 if(2 > max) { 14 max = 2; 15 start = i; 16  } 17  } 18  } 19 for(i = 3; i <= len ;i++) { 20 for(j = 0; j + i <= len; j++) { 21 if(s[j] == s[j+i-1] && dp[j+1][i+j-2]) { 22 dp[j][j+i-1] = 1; 23 if(i > max) { 24 max = i ; 25 start = j; 26  } 27  } 28  } 29  } 30 for(i = 0; i < max; i++) { 31 ans[i] = s[start + i]; 32  } 33 ans[i] = '\0'; 34 return ans; 35 }

 

转载于:https://www.cnblogs.com/LeeZz/p/4498675.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值