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

    终于找到水题了感动。。

    manacher模板都会吧。不会请点击左侧友链,找到FYJ大佬的博客,可以看他博客,或通过教他泡妹子等正常方式让他给你讲manacher。

    首先,我们在进行manager的过程中,可以求出每个位置为中心的最长回文子串长度

    那么,我们可以枚举断点,把以该点结尾的前面最长回文子串长度与从该点开头的最长回文子串长度加起来,取max,就能找到我们想要的答案了。

    每找到一个中心及它的半径,都扫一遍它的覆盖区间,进行统计?

    于是我们就找到了一个n²的优秀做法了[/手动滑稽]

    继续思考,以某个点为起点的最长长度,必定是从它的前面节点转移来的(我们在马拉车找回文串时将长度存在了这个回文串开始的地方),那么方程为start[i]=max(start[i],start[i-2]-2)  (-2是为了忽略插入的'#'号) ,以某个点为终点的长度同理,反向O(n)扫一遍就行了,最后再扫一遍统计答案,诶,好像就可以A了耶

    #include<bits/stdc++.h>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<vector>
    #include<iostream>
    #define ll long long
    #define re register
    #define inf 0x3f3f3f3f
    #define inl inline
    #define sqr(x) (x*x)
    //#define eps 1e-8
    #define debug printf("debug
    ");
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#pragma GCC optimize (2)
    //#pragma G++ optimize (2)
    using namespace std;
    //const ll mod;
    const ll MAXN=1e5+10;
    inl ll read() {
        re ll x = 0; re int f = 1;
        char ch = getchar();
        while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
        while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x * f;
    }
    inl char readc() {
        char ch=getchar();
        while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
        return ch;
    }
    inl void write(re ll x){
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    inl void writeln(re ll x){
        if(x<0) {x=-x;putchar('-');}
        write(x); puts("");
    }
    inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
    inl void FR() {
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    }
    inl void FC() {
        fclose(stdin);
        fclose(stdout);
    }
    char s[MAXN],ss[MAXN<<2];
    ll n,nn,st[MAXN<<2],ed[MAXN<<2],hw[MAXN<<2];
    void manacher() {
        ll mr=0,mid=0;
        for(re ll i=1;i<=nn;i++) {
            if(i<mr) hw[i]=min(hw[(mid<<1)-i],hw[mid]+mid-i);
            else hw[i]=1;
            while(ss[i+hw[i]]==ss[i-hw[i]]) hw[i]++;
            if(i+hw[i]>mr) {mr=i+hw[i];mid=i;}
        }
    }
    int main() {
    //  FR(); 
        scanf("%s",s+1);n=strlen(s+1);
        ss[0]=ss[1]='#';nn=n<<1|1;
        for(re ll i=1;i<=n;i++) {
            ss[i<<1]=s[i];ss[i<<1|1]='#';
        }
        manacher();
        for(re ll i=1;i<=nn;i++) {
            ed[i+hw[i]-1]=max(ed[i+hw[i]-1],hw[i]-1); 
            st[i-hw[i]+1]=max(st[i-hw[i]+1],hw[i]-1); 
        }
        for(re ll i=1;i<=nn;i+=2) st[i]=max(st[i],st[i-2]-2);
        for(re ll i=nn;i>=1;i-=2) ed[i]=max(ed[i],ed[i+2]-2);
        re ll ans=0;
        for(re ll i=1;i<=nn;i+=2) {
            if(st[i]&&ed[i]) {ans=max(ans,st[i]+ed[i]);}
        }
        writeln(ans);
    //  FC();
        return 0;
    }
  • 相关阅读:
    【linux】驱动-13-阻塞与非阻塞
    【linux】驱动-12-并发与竞态
    【linux】驱动-11-gpio子系统
    【linux】驱动-10-pinctrl子系统
    【linux】驱动-9-设备树插件
    手写Java分页模块
    JDBC连接与自定义线程池
    类加载器
    网络编程之TCP
    网络编程之UDP
  • 原文地址:https://www.cnblogs.com/20020723YJX/p/9385333.html
Copyright © 2011-2022 走看看