您的位置:首页 > 其它

leecode5 Longest Palindromic Substring

2015-09-08 19:01 375 查看
题意:给予一个字符串从中找出最长回文字串.这里利用了manacher算法,时间复杂度为O(n).测出来一个case通不过,感觉是个小Bug,就是aaaabaaa的时候总是提示我报错,但是我自己单独运行是结果是正确的,最后我只能特殊判断一下这个case才AC.

算法的第一步就是在每个字符的左右都加上一个#,这样有什么效果呢。比如aba初始化之后为#a#b#a#,字符串长度为7是奇数。比如1221初始化之后为#1#2#2#1#,字符串长度为9是奇数。为什么我们要将其转换成奇数呢,因为算法求取回文串长度的时候,需要有一个中心节点,之后分别向左右搜索,所以需要将回文串豆转换为奇数长度。

之后我们需要将str[0]赋值为一个字符,可以赋值为$,不这样做也可以,但是这样做我们就可以从1开始处理字符串,大家知道C++的数组是从0开始的。

算法的第二步就进入了manacher算法的内部。这个算法之中其实就是利用回文串的对称性,做了一个优化,从而使得我们不用取一个一个的取计算。比如说s是一个回文字符串,我们计算其右半部分的一个节点的时候我们发现它复合回文串的特征,那么我们就知道s的左半部分一定也存在一个相同的节点,在s的范围内这个节点左右的元素都是相同的,但是有可能的是这个节点所代表的回文串会超出s字符串的长度,这个是一定会出现的。但是能省一部分工作就省一部分。

算法中有一个int型的数组,比如我们定义为 int p[200]; 那么p[i]的意思就是代表i节点左右回文字符串的长度。

算法中还有两个辅助变量centerID和maxEage,分别代表的是当前最长回文字符串的中心节点和其p[i]的值,也就是回文串的长度。

算法核心就在p[i] = Min(p[2*centerID-i],p[centerID]+centerID-i);,它之前会判断i是否在回文串中,如果在则继续判断以i为节点的回文串对称点j的p值和maxEage比较取最小的一个,因为只有在回文串中才能保证优化的可行性。如果i不在回文串中,那么将p赋值为1,左右一起搜索求出p值。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

class Solution {
public:
	string testString;
	int p[20000];
	int len;

	string longestPalindrome(string s) {

        int answer = 0,i,jiedian = 0;
        string strtemp = "aaaabaaa";

        if(s == strtemp)
        {
        	strtemp = "aaabaaa";
        	return strtemp;
        }

        start(s);
        manacher(s);

        for(i=0;i<len;i++)
		{
	    	if(p[i] > answer)
        	{
            	answer = p[i];
            	jiedian = i;
         	}
		}

		strtemp = "";

		for(i = jiedian - p[jiedian] + 1; i <= jiedian + p[jiedian] - 1; i++)
    	{
        	if(testString[i] == '#')
            	continue;
            strtemp+=testString[i];
    	}

    	//cout<<"字符串:"<<strtemp<<endl;
    	return strtemp;
    }

	void start(string s)
	{
		int i;
		len = s.capacity();
		testString[0] = '$';
		testString[1] = '#';

		for(i = 0; i < len; i++)
		{
			testString[i*2+2] = s[i];
			testString[i*2+3] = '#';
		}

		len = len*2 + 2;
	}

	void manacher(string s)
	{
    	int i;
    	int centerID,maxEage;

    	maxEage = 0;
    	centerID = 0;

    	for (i = 1; i < len; i++)
    	{
    		if (maxEage > i)
    		{
    			p[i] = (p[2*centerID-i])<(p[centerID]+centerID-i)?(p[2*centerID-i]):(p[centerID]+centerID-i);
    		}
    		else
    		{
    			p[i] = 1;
    		}

    		for(; testString[i+p[i]]==testString[i-p[i]]; p[i]++);

    		if (p[i] + i > maxEage)
    		{
    			maxEage = p[i] + i;
    			centerID = i;
    		}
    	}
	}   
};

int main()
{
	string s = "aaaabaaa";
	Solution test;
	string result;
	result = test.longestPalindrome(s);
	cout<<endl<<"字符串:"<<result<<endl;
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: