• Manacher【p4555】 [国家集训队]最长双回文串


    题目描述

    顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同)。

    输入长度为 n 的串 S ,求 S 的最长双回文子串 T ,即可将 T 分为两部分 X ,Y,(|X|,|Y|≥1且 X 和 Y 都是回文串。

    xjb分析

    首先给出双回文串定义:

    ----双回文串A是指一个可以被拆分成两个部分(B和C)的字符串 A=B+C, 且B和C都是回文串的串, A自己本身可以不是回文串.

    看到回文很容易想到manacher算法

    其实正解就是manacher (⊙o⊙)…

    我相信大家都理解如何去处理字符串的奇偶,所以不再赘述~~

    如果不会manacher还是先去敲板子-->manacher

    过程:

    因为双回文串是可以拼接得到的,
       所以我们可以预先处理出来数组RL[i](即代表以i为对称轴的最大回文半径)
    然后我们可以定义这么两个东西
       1.:l[i]代表i位置所在回文串中的最右端的位置
       2.:r[i]代表i位置所在回文串中的最左端的位置
       我们可以算出来这个东西。
       因此通过左右拼接就可以得到我们的双回文串了
       
       完_(:з」∠)_完
    

    (可能排版不太好,请揍我谅解)

    ------------------ 代码------------------

    #include<bits/stdc++.h>
    #define IL inline
    #define RI register int
    #define N 100010
    char s[N<<1],ch[N];
    int MaxRight,center,len;
    int RL[N<<1],l[N<<1],r[N<<1];
    int pos,ans;
    int main()
    {
    	std::cin>>ch;
    	len=strlen(ch);
    	for(RI i=0;i<len;i++)s[2*i+1]=ch[i];
    	len=2*len+1;//这里不要忘记变化长度! 
    	RL[0]=1;
    	for(RI i=1;i<len;i++)
    	{
    		if(i<=MaxRight)
    			RL[i]=std::min(MaxRight-i,RL[2*center-i]);
    		else 
    			RL[i]=1;
    		while(i-RL[i]>=0&&RL[i]+i<len&&s[i+RL[i]]==s[i-RL[i]])
    							++RL[i];
    		if(i+RL[i]-1>MaxRight)
    			MaxRight=i+RL[i]-1,center=i;//注意更新操作 
    	}
    	for(RI i=0;i<len;i++)
    		for(;pos<=i+RL[i]-1;pos++)
    			l[pos]=i;//概念和上面讲的一样 
    	pos=len;
    	for(RI i=len-1;i>=0;i--)
    		for(;pos>=i-RL[i]+1;pos--)
    			r[pos]=i;//概念同上面讲的一样 
    	for(RI i=0;i<len;i++)
    		ans=std::max(ans,abs(l[i]-r[i]));//为了保险 ,貌似可以直接减 emmm 
    	std::cout<<ans;
    }
    

    如果哪里写的好 请私信我emmm

  • 相关阅读:
    2013年3月17日星期日
    2013第11周一
    2013年第11周二
    2013年第11周三今天开发踩过的坑
    2013第11周四开发摸索
    2013第10周六项目中用到的前端技术学习1
    PHP 数组使用之道
    快递查询API接口集成,有需要的可以直接用
    PHP intval() 函数
    巧用 PHP 数组函数
  • 原文地址:https://www.cnblogs.com/-guz/p/9622712.html
Copyright © 2020-2023  润新知