关闭

最长回文子串的几种解法

标签: leetcode
35人阅读 评论(0) 收藏 举报
分类:

这几天在刷leetcode,碰到了最长回文字串问题,网上查资料发现至少有4种解法,在学习完每种方法之后,写个博客总结下。参考了别人写的博客,可能会有些雷同。

参考资料:http://blog.csdn.net/kangroger/article/details/37742639

                 http://www.cnblogs.com/biyemyyhjob/archive/2012/10/04/2711527.html

最长回文子串问题:给出一个字符串str,求它的最长回文字串。回文字符串是指顺序和逆序是同一字符串的字符串。

解法1:暴力求解法

        根据习惯,首先想一个暴力解法,这个问题的暴力解法思想是这样:遍历每一个子串,判断是否是回文串,并维护一个最长回文起始地址和最大回文长度。求每一个子串时间复杂度O(N^2),判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。代码如下:

	string longestPalindrome(string s) {
		int len = s.size();//字符串长度 
		if (len == 0) return " ";
		int maxlen = 0;//最长回文字符串长度  
		int start;//最长回文字符串起始地址  
		for (int i = 0; i<len; i++)//起始地址  
			for (int j = i; j < len; j++)//结束地址  
			{
				int tmp1, tmp2;
				for (tmp1 = i, tmp2 = j; tmp1 <= tmp2; tmp1++, tmp2--)//判断是不是回文  
				{
					if (s.at(tmp1) != s.at(tmp2))
						break;
				}
				if (tmp1 > tmp2 && j - i + 1 > maxlen)
				{
					maxlen = j - i + 1;
					start = i;
				}
			}
		return s.substr(start, maxlen);//求子串  
	}


解法2:动态规划法

回文字符串的以中心对称的子串也是回文,比如"abccba"是回文串,则"cc","bccb"也是回文。

可以用p[i][j]来表示以下标i开始,下标j结束的一个子串,则定义p[i][j]=1表示这个子串是回文串,p[i][j]=0不是回文串。可知对于所有i=0~length(str),

有p[i][i]=1,如果str[i]==str[i+1],则p[i][i+1]=1.这样就判断了长度为1和2的所有子串是不是回文串。更长长度的子串的判断,就可以根据其中心对称

子串是否是回文串以及两头的字符是否一样来判断了。空间复杂度O(N^2),时间复杂度O(N^2)。代码如下:

string longestPalindrome(string s) {
	const int length = s.size();
	int maxlength = 1;
	int start = 0;
	bool P[1000][1000] = { false };
	for (int i = 0; i<length; i++)//初始化准备  
	{
		P[i][i] = true;
		if (i<length - 1 && s.at(i) == s.at(i + 1))
		{
			P[i][i + 1] = true;
			start = i;                           //最后一个长度为2的回文串的起始下标
			maxlength = 2;
		}
	}
	for (int len = 3; len<=length; len++)//子串长度  
		for (int i = 0; i <= length - len; i++)//子串起始地址  
		{
			int j = i + len - 1;//子串结束地址  
			if (P[i + 1][j - 1] && s.at(i) == s.at(j))
			{
				P[i][j] = true;
				maxlength = len;
				start = i;
			}
		}
	return s.substr(start, maxlength);
}

解法3:中心扩展法

中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。代码如下:

string longestPalindrome(string &s)
    {
        const int length = s.size();
	    int maxlength = 1;
	    int start = 0;
	    for (int i = 0; i < length; i++)
    	{
	    	int h = i - 1, k = i, j = i + 1;
	    	while (k >= 0 && j < length && s[k] == s[j])
	    	{
		    	if (maxlength <= j - k + 1)
		    	{
		    		maxlength = j - k + 1;
		    		start = k;
		    		k--;
		    		j++;
		    	}
		    	else
		    	{
		    		k--;
		    		j++;
		    	}
	    	}
	    	h = i - 1, k = i, j = i + 1;
	    	while (h >= 0 && j < length && s[h] == s[j])
	    	{
		    	if (maxlength <= j - h + 1)
		    	{
		    		maxlength = j - h + 1;
		    		start = h;
		    		h--;
		    		j++;
	    		}
	    		else
	    		{
		    		h--;
		    		j++;
		    	}
	    	}
    	}
	    return s.substr(start, maxlength);
    }

 

解法4:manacher法

参考http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html  代码如下:

string longestPalindrome(string &s)
    {
        string str;
        str += "$#";
        for(int i = 0; i < s.size(); i++)
        {
            str += s[i];
            str += "#";
        }
        int *p = new int[str.size() + 1];
        memset(p, 0, sizeof(p));

        int mx = 0, id = 0;
        for(int i = 1; i <=  str.size(); i++)
        {
            if(mx > i)
            {
                p[i] = (p[2*id - i] < (mx - i) ? p[2*id - i] : (mx - i));
            }
            else
            {
                p[i] = 1;
            }

            while(str[i - p[i]] == str[i + p[i]])
                p[i]++;

            if(i + p[i] > mx)
            {
                mx = i + p[i];
                id = i;
            }

        }
        int max = 0, ii;
        for(int i = 1; i < str.size(); i++)
        {
            if(p[i] > max)
            {
                ii = i;
                max = p[i];
            }
        }

        max--;

        int start = ii - max ;
        int end = ii + max;
        char buf[1000];
        memset(buf,'\0',1000);
        int k=0;
        for(int i = start; i <= end; i++)
        {
            if(str[i] != '#')
            {
                buf[k++] = str[i];
            }
        }
        delete  p;
        return buf;
    }






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:34次
    • 积分:10
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档