Leetcode:Longest Palindromic Substring


             没弄过ACM的人表示刷leetcode还是有压力的!!!!看着别人的神思路,和对题目的分析还有入手点,让我真后悔大一没去搞搞ACM锻炼锻炼思维啊= =    目前比较遗憾的两件事就是大一没参加到学生会,和没有刷ACM题。

   

             就好比这题,求最长回文子串    Given a string S, find the longest palindromic substring in S。  判断回文这个简单,但是在一个字符串找子串而且找是回文的就稍微复杂了,当然最直接的思路是列出所有子串可能性,并一一判断是否为回文,然而这种算法效率很低,结果超时。


          于是上网找了答案,说是一种思路是动态规划。虽然大二期间自己有做过一些ACM题,有涉及动态规划,觉得用到动态规划解决的算法题非常的巧妙,但是死活不知道dp数组应该如何定义,到现在还不太理解动态规划的适用处,希望以后多加练习能有感觉吧。以下是动态规划对题目的一些分析。


1.定义dp数组bool  dp[ 1000][1000 ] ;(别问我怎么来的,就是觉得很厉害,我也在慢慢领悟 = = ) dp [ i ] [ j ]记录  字符串s  位置 i 到位置  j是否为回文。


2.位置 i  到  位置  j是回文  前提是 s[  i ] ==s[ j ],然后判断位置 i + 1 到 j - 1是否是回文。


3.若是,则判断当前回文子串是否是最长,如果是,则记录位置,函数末尾返回。否则继续。


以下是代码:

string longestPalindrome(string s){
	
	int length = s.size();
	
	if (length == 0){
		return "";
	}

	if (length == 1){
		return s;
	}

	bool dp[1000][1000];
	int max_length = 0;
	int result_pos1 = 0;
	int result_pos2 = 0;


	for (int i = 0; i < length; i++){
		for (int j = 0; j < length; j++){
			if (i == j ){
				dp[i][j] = true;
			}
			else {
				dp[i][j] = false;
			}
		}
	}

	for (int i = length - 1; i >= 0; i--){
		for (int j = i; j<s.length(); j++){
			
			if (s[i] == s[j] && (i+1>j-1||dp[i+1][j-1])){
				dp[i][j] = true;
				if (j - i + 1>max_length){
					max_length = j - i + 1;
					result_pos1 = i;
					result_pos2 = j;
				}
			}
		}
	}

	return s.substr(result_pos1,result_pos2 - result_pos1 +1);
}

需要注意以下这个问题,贴上错误代码,仅修改了赋值dp数组时候的i  j起始边界!

/*
     错误代码
*/
string longestPalindrome(string s){
	
	cout << s << endl;
	int length = s.size();
	
	if (length == 0){
		return "";
	}

	if (length == 1){
		return s;
	}

	bool dp[1000][1000];
	int max_length = 0;
	int result_pos1 = 0;
	int result_pos2 = 0;


	for (int i = 0; i < length; i++){
		for (int j = 0; j < length; j++){
			if (i == j ){
				dp[i][j] = true;
			}
			else {
				dp[i][j] = false;
			}
		}
	}
	/*
		这样设置边界错误!导致在判断dp[i][j]的时候,由于先判断较长的子串i到j是否为回文时,依照的是判断i+1到j-1是否为回文
		但由于更小的范围dp[i+1][j-1]还处于初始化默认的状态,而未被计算后重新赋值,所以遍历时应该从最小子串开始遍历!!
	*/
	for (int i = 0; i<length;i++){
		for (int j = i; j<s.length(); j++){
			
			if (s[i] == s[j] && (i+1>j-1||dp[i+1][j-1])){
				cout << "Match when i is " << i << "   j is " << j << "   length is " << j - i + 1 << "    max_length is " << max_length << endl;
				dp[i][j] = true;
				if (j - i + 1>max_length){
					max_length = j - i + 1;
					result_pos1 = i;
					result_pos2 = j;
				}
			}
		}
	}

	cout << "result ....  pos1 is " << result_pos1 << "    pos2 is " << result_pos2 << endl;
	return s.substr(result_pos1,result_pos2 - result_pos1 +1);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值