zoukankan      html  css  js  c++  java
  • [BZOJ2565] 最长双回文串

    传送门

    题目大意:求最长的连续的两个回文串的长度

    题解:Manacher+枚举

    首先知道两个连续回文串的中间的那个字符一定是‘#’。

    然后枚举‘#’。看以这个字符为中心,左右最长的回文串

    有多长。

    now+Len[now]>i时,那么以now为中心的回文串是在i左边

    的,尽管超出了i,可以左右砍掉嘛//。i-now就是i左边的回文

    串的长度。一开始不太明白i-now为什么是,因为还有'#'啊,写了

    几个符号i-now就是左边回文串的长度。

    ps:如果有哪位dalao看到这篇题解,可以告诉我更好的理解方法吗?orz

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100009
    using namespace std;
     
    int len,now,ans;
    char s[maxn*2],str[maxn*2];
    int Len[maxn*2],l[maxn*2],r[maxn*2];
     
    void getstr(){
        int k=0;str[0]='$';
        for(int i=0;i<len;i++){
            str[++k]='#';str[++k]=s[i];
        }
        str[++k]='#';len=k;
    }
     
    void Manacher(){
        int mx=0,id;getstr();
        for(int i=1;i<=len;i++){
            if(mx>i)Len[i]=min(mx-i,Len[2*id-i]);
            else Len[i]=1;
            while(str[i+Len[i]]==str[i-Len[i]])Len[i]++;
            if(i+Len[i]>mx)mx=i+Len[i],id=i;
        }
    }
    int main(){
        scanf("%s",&s);len=strlen(s);
        Manacher();
        for(int i=1;i<=len;i++){
            if(str[i]=='#'){
                while(now+Len[now]<i)now++;
                l[i]=i-now;
            }
        }now=len;
        for(int i=len;i>=1;i--){
            if(str[i]=='#'){
                while(now-Len[now]>i)--now;
                r[i]=now-i;
            }
        }
        for(int i=1;i<=len;i++)ans=max(ans,l[i]+r[i]);
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    Unity-WIKI 之 AllocationStats(内存分配)
    Unity-WIKI 之 DebugLine
    Unity-WIKI 之 DebugConsole
    Unity-WIKI 之 DrawArrow
    Unity 2D Sprite Lighting
    Unity 2D Touch Movement
    [Unity2D]2D Mobile Joystick
    DragRigidbody2D
    Finger Gestures 3.1
    2D Skeletal Animation Ready
  • 原文地址:https://www.cnblogs.com/zzyh/p/7679057.html
Copyright © 2011-2022 走看看