zoukankan      html  css  js  c++  java
  • Manacher【p1210】回文检测

    题目描述--->P1210 回文检测

    分析:

    看到回文显然想到了manacher算法(线性求解回文串问题

    如果不了解还是去敲一下板子,学习一下比较好.-->manacher

    题目要求我们求出只包含字母的回文串的长度.

    如果你会manacher,这很简单.

    只需要在输入之后处理一下我们得到的串即可.

    这题的难点在于,如何输出原串


    吐槽

    本来以为求出我们的最长回文半径的最中间的位置的字符,判断其左右两侧遇到的第一个字符是否相等,如果相等我们就可以一直扩展过去,直至无法匹配.

    感觉这种被卡的概率还是很低的...

    兴冲冲地码了100多行.然而还是被卡了,绝望地很.


    解决

    首先明确:

    s数组为我们的原字符数组.
    str数组为我们只含有大写(小写)字母的字符数组
    ss数组为我们用于跑manacher的字符数组
    

    因此考虑去记录字符在原数组中的位置.

    很容易将我们转化后的数组记录.
    这样记录↓

    for(RI i=0;i<l;i++)//l为我们原串长度,从l=0开始记录.
        {
            if((s[i]>='a' and s[i]<='z') or (s[i]>='A' and s[i]<='Z'))
            str[len]=s[i],pos[len]=i,len++;
            //我们只存储为字母的情况.
        }
    

    处理我们得到的数组↓

    for(RI i=0;i<len;i++)
        {
            if(str[i]>='a' and str[i]<='z')
                str[i]-=32;
        }//在这里将小写转为大写.
        //也可以将大写转为小写
        //视个人爱好而定.
    

    此时我们已经记录了某一位置对应的原串位置.

    接下来就是我们的manacher操作了!

    处理我们用于manacher的数组↓

    for(RI i=0;i<len;i++)ss[2*i+1]=str[i];
        ll=2*len+1;//这里记得变换长度.
    //这里我并没有进行插入字符的操作
    //是因为我们的字符数组默认为空.
    //这样的处理操作会使得中间空出一些位置.从而达到插入字符的效果.
    

    我们现在需要考虑的是如何对我们用于manacher操作的数组进行标记操作,即对应原串位置.

    因为我们用于manacher的数组ss[2i+1]对应str[i],
    所以我们的数组poss[2
    i+1]也会对应pos[i].

    所以我们的答案就很明显了.

    最左端位置就是le=i-(RL[i]-1)+1
    最右端位置就是ri=i+(RL[i]-1)-1
    其中RL[i]-1代表以i为对称轴的回文子串长度
    

    所以我们枚举poss[le]到poss[ri]输出答案即可.

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

    #include<bits/stdc++.h>
    #define IL inline
    #define RI register int
    char s[200008],str[200008],ss[400008];
    int l,len,pos[200008],RL[200008],ll,ans,le,ri,poss[200008];
    int main()
    {
        while(~(s[l]=getchar())){l++;}//输入还是看了其他人的 emmmm,自己写的一个炸了 emmm
        for(RI i=0;i<l;i++)
        {
            if((s[i]>='a' and s[i]<='z') or (s[i]>='A' and s[i]<='Z'))
            str[len]=s[i],pos[len]=i,len++;
        }
        for(RI i=0;i<len;i++)
        {
            if(str[i]>='a' and str[i]<='z')
                str[i]-=32;
        }
        int MaxRight=0,center=0;RL[0]=1;
        for(RI i=0;i<len;i++)ss[2*i+1]=str[i],poss[2*i+1]=pos[i];//这里的对应操作.
        ll=2*len+1;
        for(RI i=1;i<ll;i++)
        {
            if(i<=MaxRight)
                RL[i]=std::min(RL[2*center-i],MaxRight-i);
            else RL[i]=1;
            while(i-RL[i]>=0 and i+RL[i]<ll and ss[i+RL[i]]==ss[i-RL[i]])
                RL[i]++;
            if(i+RL[i]-1>MaxRight)MaxRight=i+RL[i]-1,center=i;
            if(RL[i]-1>ans)
            {
            	ans=RL[i]-1;
            	le=i-RL[i]+2;
            	ri=i+RL[i]-2;
            }
        }
        printf("%d
    ",ans);
        for(RI i=poss[le];i<=poss[ri];i++)std::cout<<s[i];
    }
    
    除特殊声明外,本博客作品均由顾z创作。 未经博主允许,不得转载
  • 相关阅读:
    MySQL Backup mysqldump 常用选项与主要用法--转发
    openssl 之RSA加密
    Windows 之Dll/lib导出
    缓存雪崩、击穿、穿透
    时间复杂度
    分布式事务
    mysql主从复制与读写分离
    什么是消息队列?
    微服务架构演化
    高并发问题常规思路
  • 原文地址:https://www.cnblogs.com/-guz/p/9612862.html
Copyright © 2011-2022 走看看