字符串--最长回文子串(暴力讲解+Manacher)

问题描述:给你一个字符串str,若子串s是回文串,则称s为str的回文子串,求s的最大长度

解法一:暴力匹配

              对每一个字符,假定位置为i,匹配判断i+1与i-1位置是否相等,相等ans长度加一,否则停止。

        字符串--最长回文子串(暴力讲解+Manacher)_第1张图片

              对奇数,ans=1;对偶数,ans初始为0.(不知道奇数偶数,两种都要写,最后取较大值)。奇数偶数都要判断,代码很长,复杂度O((2*N+1)*N)=O(N^2).

              比起一般暴力三方快一点。

解法二:Manacher

     严格复杂度O(N)       

     step1:预处理,将奇偶变为奇数。

             对于一个串str长度为n,有n-1个空格,首位有两个,对这些空处理,长度变成2n+1。

 

字符串--最长回文子串(暴力讲解+Manacher)_第2张图片

     可以加str中不存在的东西,比如#。

             step2: 构造数组p[n]

            数组p[i]来记录字符串s[i]最长回文串向左向右扩张p[i]长度的最大值。

         字符串--最长回文子串(暴力讲解+Manacher)_第3张图片

     如图,对应的关系,p[i]-1正好是原字符串最长回文子串的长度。

     如何求p[i]数组?

      求p[i]时,p[1]....p[n]是已知的。

      对任意位置i,可以扩张的范围是i±p[i],这个范围都是回文的。对于k+p[k](k=1,2,.....i-1)有最大值记为mx,有一个id(id的值就是前面mx取得最大值对应的p[k]的k的值),

     i关于id的位置是 j  (j=2*id-i),mx关于id对称点是my (my=2*id-mx).

     那么,从id两侧(从my到mx)一定是回文的。

    如果i+p[j]长度在mx之内就取它,如果i+p[j]长度不可控,在mx之外,就取mx-i

字符串--最长回文子串(暴力讲解+Manacher)_第4张图片

字符串--最长回文子串(暴力讲解+Manacher)_第5张图片

    总之取  p[i]=min(p[2*id-i],mx-i)

                     没有可利用的p[i]=1;接下来该怎样就怎样。

 

#include 
#include 
#include 
using namespace std;
char s[10000],s2[100000];
int p[10000];
int size;
void Manacher(char *s,int * p)
{
	 size=strlen(s);
	p[0]=1;
	int id=0;
	int mx=1;
	for(int i=1;ii)
		{
			p[i]=min(p[2*id-i],mx-i);
		}
		else
		{
			p[i]=1;
		}
		for(;s[i+p[i]]==s[i-p[i]]&&(i-p[i]>=0);p[i]++);
		if(mx

字符串--最长回文子串(暴力讲解+Manacher)_第6张图片

你可能感兴趣的:(字符串)