您的位置:首页 > 其它

leetcode [005] : Longest Palindromic Substring

2015-09-15 10:59 363 查看
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.

思路:

两种做法

第一种做法:动态规划

1、设f[i][j]表示从下标i到j的字符串是不是回文串

2、f[i][j] = (f[i + 1][j - 1] && s[i] == s[j])

3、这个动态规划的阶段划分根本就是减少2的长度后,看能不能继续扩展

4、边界条件:

a.单个字符都是回文的

b.既然要砍掉2的长度才能判断以前的阶段,那么我们可以直接构建2的长度为边界条件(if (s[k] == s[k + 1]) 则是回文的)

5、驱动阶段划分的是字符串的长度

注意:很遗憾的是,上面的算法没有能够通过leetcode,错误原因是内存不够

分析一下,字符串最长如果是1000的话,那么存储空间就是1000 * 1000

为了能让动态规划也能够通过leetcode oj,我把上面的状态转移方程的f[i][j]的意义改为"以i下标开始,j长度的字符串是否为回文"

这样在动态开辟空间的时候,能够节约一半的空间,因为i越靠后,j的值也就越小

源代码如下:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Solution {
public:
string longestPalindrome(string s) {
int iLen = s.size();
if (iLen == 0) return s;

bool ** pArr = NULL;
pArr = (bool **)new bool *[iLen];
for (int i = 0; i < iLen; ++i)
{
pArr[i] = new bool[iLen - i + 1];
}

int iMaxLen = 0;
string strResult;

for (int i = 1; i <= iLen; ++i)
{
for (int j = 0; j <= iLen - i; ++j)
{
if (i == 1)
{
pArr[j][1] = true;
}
else if (i == 2)
{
if (s[j] == s[j + 1])
{
pArr[j][2] = true;
}
else
{
pArr[j][2] = false;
}
}
else if (pArr[j + 1][i - 2] && s[j] == s[j + i - 1])
{
pArr[j][i] = true;
}
else
{
pArr[j][i] = false;
}

if (pArr[j][i] && i > iMaxLen)
{
iMaxLen = i;
strResult = s.substr(j, i);
}
}
}

for (int i = 0; i < iLen; ++i)
{
delete [] pArr[i];
}
delete [] pArr;

return strResult;
}
};

int main()
{
Solution a;
string strResult = a.longestPalindrome("aa");
printf("%s\n", strResult.c_str());
system("pause");
return 0;
}


第二种做法:

用Manacher算法,具体的Manacher算法可以去网上搜索,我是看的如下这篇文章
http://www.open-open.com/lib/view/open1419150233417.html
其主要思想是通过回文串的对称性,查看自己的子串是否也是回文串,当不满足条件或者越界的时候,就继续向后遍历

具体的算法,参见网上的各文章,自己演算一遍就很清楚了

我的代码有一些冗余,但在leetcode上也算跑出了4ms的好成绩,差强人意吧

源代码如下:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Solution {
public:
string longestPalindrome(string s) {
string strConvert;
if (s.size() <= 1) return s;
for (int i = 0; i < s.size(); ++i)
{
strConvert += '#';
strConvert += s[i];
}
strConvert += '#';

int p0 = 0, p = 0, j;
int * pLen = new int[strConvert.size()];
pLen[0] = 1;
int iMaxLen = 1;
int iMaxLabel = 0;
int iCount = 0;
for (int i = 1; i < strConvert.size(); ++i)
{
if (i <= p)
{
j = 2 * p0 - i;
if (pLen[j] + i - 1 < p)
{
pLen[i] = pLen[j];
}
else
{
iCount = p - i + 1;
int k = p + 1;
while (k < strConvert.size() &&
2 * i - k >= 0 &&
strConvert[k] == strConvert[2 * i - k])
{
++iCount;
++k;
}
pLen[i] = iCount;
p0 = i;
p = i + iCount - 1;
}
}
else
{
iCount = 1;
int k = i + 1;
while (
k < strConvert.size() && \
2 * i - k >= 0 && \
strConvert[k] == strConvert[2 * i - k])
{
++iCount;
++k;
}
pLen[i] = iCount;
p0 = i;
p = i + iCount - 1;
}

if (pLen[i] > iMaxLen)
{
iMaxLen = pLen[i];
iMaxLabel = i;
}
}

delete [] pLen;

string strResult;
if (iMaxLabel % 2)
{
strResult = s.substr(iMaxLabel / 2 - (iMaxLen - 1) / 2, iMaxLen - 1);
}
else
{
strResult = s.substr((iMaxLabel - 1) / 2 - (iMaxLen - 1) / 2 + 1, iMaxLen - 1);
}

return strResult;
}
};

int main()
{
Solution a;
string strResult = a.longestPalindrome("abba");
printf("%s\n", strResult.c_str());
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: