码迷,mamicode.com
首页 > 其他好文 > 详细

LPS(最长回文子序列)

时间:2018-02-18 10:33:38      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:etc   return   最长回文子串   long   情况下   ali   solution   代码   方法   

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

 

Example:

Input: "cbbd"

Output: "bb"

  这也是《算法导论》中的一个练习题,先给一个自己想的算法(最坏情况的时间复杂度为O(n2)):

class Solution {
public:
    string longestPalindrome(string s) {
        if (s.size() == 0)
			return 0;
		
		int i = 0, j = s.size() - 1;
		int flag = 0;
		int subscript = j;

		string s1 = "";

		while (i < j)
		{
			while (i < j)
			{
				if (s[i] == s[j])
				{
					s1 += s[j];
					subscript = --j;
					i++;
					flag = 1;
					break;
				}
				j--;
				flag = 0;
			}
			if (!flag)
			{
				j = subscript;
				i++;
			}
		}

		int k = 0, l = s.size() - 1;
		flag = 0;
		subscript = l;

		string str = s;
		reverse(str.begin(), str.end());
		string s2 = "";

		while (k < l)
		{
			while (k < l)
			{
				if (str[k] == str[l])
				{
					s2 += str[l];
					subscript = --l;
					k++;
					flag = 1;
					break;
				}
				l--;
				flag = 0;
			}
			if (!flag)
			{
				l = subscript;
				k++;
			}
		}
		int l1 = s1.size(), l2 = s2.size();
		s1 = l2 > l1 ? s2 : s1;

		if (i >= k && i > j)
		{
			string str = s1;
			reverse(str.begin(), str.end());
			s1 += str;
		}
		else if (k > i && k > l)
		{
			string str = s1;
			reverse(str.begin(), str.end());
			s1 += str;
		}
		else
		{
			string str = s1;
			reverse(str.begin(), str.end());
			s1 += s[l1 >= l2 ? i : k];
			s1 += str;
		}

		return s1;
    }
};

  两段二重循环的目的是:第一段从右到左缩短str来得到回文子串s1;第二段将原来的字符串反转,然后同样的方式得到一个回文子串s2,然后返回最长的。

  但结果Leetcode以这种方式拒绝了:

Input:
"abcda"
Output:
"ada"
Expected:
"a"

  但我不觉得我的错了啊...书上说:character,返回:carac,但在Leetcode竟然错了。。。看来和书上问题并不太一样。

  完整代码(可以返回最长回文子串的长度):

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

class Solution {
public:
	std::string LPS(std::string str)
	{
		if (str.size() == 0)
			return 0;
		
		int r1 = 1;
		int i = 0, j = str.size() - 1;
		int flag = 0;
		int subscript = j;

		std::string s1 = "";

		while (i < j)
		{
			while (i < j)
			{
				if (str[i] == str[j])
				{
					s1 += str[j];
					subscript = --j;
					i++;
					r1++;
					flag = 1;
					break;
				}
				j--;
				flag = 0;
			}
			if (!flag)
			{
				j = subscript;
				i++;
			}
		}

		int r2 = 1;
		int k = 0, l = str.size() - 1;
		flag = 0;
		subscript = l;

		std::string s = str;
		std::reverse(s.begin(), s.end());
		std::string s2 = "";

		while (k < l)
		{
			while (k < l)
			{
				if (s[k] == s[l])
				{
					s2 += s[l];
					subscript = --l;
					k++;
					r2++;
					flag = 1;
					break;
				}
				l--;
				flag = 0;
			}
			if (!flag)
			{
				l = subscript;
				k++;
			}
		}
		int l1 = s1.size(), l2 = s2.size();
		s1 = l2 > l1 ? s2 : s1;

		if (i >= k && i > j)
		{
			std::string s = s1;
			std::reverse(s.begin(), s.end());
			s1 += s;
			r1--;
		}
		else if (k > i && k > l)
		{
			std::string s = s1;
			std::reverse(s.begin(), s.end());
			s1 += s;
			r2--;
		}
		else
		{
			std::string s = s1;
			std::reverse(s.begin(), s.end());
			s1 += str[l1 >= l2 ? i : k];
			s1 += s;
		}

		r1 *= 2;
		r1 = i > j ? r1 : r1 - 1;

		r2 *= 2;
		r2 = k > l ? r2 : r2 - 1;

		r1 = l1 >= l2 ? r1 : r2;
		std::cout << r1 << std::endl;
		return s1;
	}
};

int main()
{
	Solution solve;
	std::string str = "abcda";

	std::cout << str << std::endl;
	std::cout << solve.LPS(str) << std::endl;
	getchar();
	return 0;
}

  最开始我想到的办法是通过反转s,得到字符串s‘,然后把问题转化成求LCS,但我发现不符合书上要求。但看样子,Leetcode的问题可以用这个方法解决。dp解法我还不会。。。没得到最优子结构,所以推不出递归式...emmm...但我的这个算法可以解决书上的这个问题,平均情况是很快的:我估计能在O(nlgn)以内,最好情况下为:O(n);但最坏情况下,比如:abcdef这类的就是O(n2)。

LPS(最长回文子序列)

标签:etc   return   最长回文子串   long   情况下   ali   solution   代码   方法   

原文地址:https://www.cnblogs.com/darkchii/p/8452411.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!