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

leetcode [005] : Longest Palindromic Substring

时间:2015-09-15 12:23:54      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

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;
}

 

leetcode [005] : Longest Palindromic Substring

标签:

原文地址:http://www.cnblogs.com/lqy1990cb/p/4809628.html

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