Manacher算法

Manacher算法详解及模板(求解最长回文串)

【面试现场】如何找到字符串中的最长回文子串?

Manacher算法详解

以上的几篇博客推荐给大家,嘿嘿

Manacher算法是查找一个字符串的最长回文子串的线性算法。

回文的定义:正反读都是一样的字符串叫做回文串。如:madam,lol,oppo,zz,甚至连单字符都可以被称为回文(串)。

上面的例子可以看出,回文串可以分为两种:奇数回文和偶数回文。

Manacher算法可以将长度为奇数和偶数的回文串一起考虑:在原字符串的相邻字符串之间插入一个分隔符,字符串的首尾也要分别添加,注意分隔符必须是原字符串中没有出现过的,最好在第一个#之前和最后一个#之后再加上一个特殊字符(而这不一样)以防越界

 

Len数组的介绍(Len[i] 又可以称为该点的回文半径)

Len数组有一个性质,那就是Len[i]-1就是该回文子串在原字符串S中的长度,至于证明,首先在转换得到的字符串T中,所有的回文字串的长度都为奇数,那么对于以T[i]为中心的最长回文字串,其长度就为2*Len[i]-1,经过观察可知,T中所有的回文子串,其中分隔符的数量一定比其他字符的数量多1,也就是有Len[i]个分隔符,剩下Len[i]-1个字符来自原字符串,所以该回文串在原字符串中的长度就为Len[i]-1。

根据之前已经匹配好的最大的回文半径R,设当前点的回文半径为r,r的起点一定大于R的起点,因为在处理r的时候,R已经处理好了

è¿éåå¾çæè¿°

è¿éåå¾çæè¿°

根据对称性,找到r1,从而可以确定r的回文半径

è¿éåå¾çæè¿°

è¿éåå¾çæè¿°

红色和红色对对称,蓝色和蓝色对称,所以,r和r1仍然关于R中心点对称,也就是r的回文半径依旧等于r1的回文半径.

è¿éåå¾çæè¿°

è¿éåå¾çæè¿°

 所以黄色的部分还需要继续匹配下去,来判断是否需要扩大R

 

可以用VS单步调试,看一下s数组,mx,pos,Len数组的变化

void init()
{
	int i,k = 0;
	s[k++] = '@';
	len = strlen(ans);
	for(i=0;i<len;i++)
	{
		s[k++] = '#';
		s[k++] = ans[i];
	}
	s[k++] = '#';
	s[k++] = '$';
	s[k] = '\0';
	len = k;
	
}

int Manacher()
{
    init();
    int mx=0,pos,cnt=1;
    for(int i=1;i<len;i++)
    {
        if(mx>i)
        	Len[i]=min(Len[2*pos-i],mx-i);
        else 
        	Len[i] = 1; 
        while(s[i+Len[i]]==s[i-Len[i]]) 
            Len[i]++; 
        if(Len[i]+i>mx)
        {
        	mx = Len[i]+i;
		pos = i;
	}
	cnt = max(Len[i],cnt);
    }
    return cnt-1;
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值