前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字符串--最长回文子串(暴力讲解+Manacher)

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

作者头像
用户2965768
发布2018-08-30 16:23:02
1.2K0
发布2018-08-30 16:23:02
举报
文章被收录于专栏:wymwym

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

解法一:暴力匹配

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

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

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

解法二:Manacher

     严格复杂度O(N)       

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

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

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

             step2: 构造数组p[n]

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

     如图,对应的关系,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

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

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

#include <cstring>
#include <iostream>
#include <algorithm>
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;i<size;i++)
	{
		if(mx>i)
		{
			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<i+p[i])
		{
			mx=i+p[i];
			id=i;
		}
	}
	
} 

int main()
{
	while(1)
	{
	scanf("%s",s2);
	size=strlen(s2);
	
	for(int i=0;i<2*size+1;i++)
	{
		s[i]='#';
		s[++i]=s2[i/2];
	}
printf("%s\n",s);
	Manacher(s,p);

for(int i=0;i<size;i++) 
	printf("%d%c",p[i]-1," \n"[i==size-1]); 
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月05日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档