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

    传送门

    看过题之后,感觉似乎最长双回文串是可以由两个回文串拼接出来的?

    于是乎我就有了一种算法!每次用manacher求出当前最大回文半径的同时,处理出每个一个点向右能拓展的最远的回文串长度和向左能拓展的回文串长度,就有如下递推:

        mr[i-p[i]+1] = max(mr[i-p[i]+1],p[i]-1);
        ml[i+p[i]-1] = max(ml[i+p[i]-1],p[i]-1);

    之后我兴致冲冲的用p[i] + max(mr[i+p[i]],ml[i-p[i]])去更新答案,然后WA了。

    因为答案有可能不是会选取每个最长的回文串,你这样默认选取了至少一个当前最长的回文串。

    难道我们的拼接大业就完不成了吗?不,不会的!

    我们发现通过ml,mr的性质可以递推出,一个点能向左/右拓展的最远的回文串,等于其后/前一个点能拓展出的最长长度-1.这样的话,我们就能通过递推求出每一个点的情况,也就不会每次强制性取一个最大值了。

    然后我们用每个点两者之和更新答案即可。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 10000005;
     
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >='0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    char s[M<<1],c[M];
    int p[M<<1],ml[M<<1],mr[M<<1],mx,mid,len,ans;
    
    int change()
    {
        int l = strlen(c),j = 2;
        s[0] = '!',s[1] = '#';
        rep(i,0,l-1) s[j++] = c[i],s[j++] = '#';
        s[j] = '&';
        return j;
    }
    
    void manacher()
    {
        len = change(),mx = mid = 1;
        rep(i,1,len-1)
        {
        if(i < mx) p[i] = min(mx-i,p[(mid<<1)-i]);
        else p[i] = 1;
        while(s[i-p[i]] == s[i+p[i]]) p[i]++;
        if(mx < i + p[i]) mid = i,mx = i + p[i];
        mr[i-p[i]+1] = max(mr[i-p[i]+1],p[i]-1);
        ml[i+p[i]-1] = max(ml[i+p[i]-1],p[i]-1);
        }
    }
    
    int main()
    {
        scanf("%s",c);
        manacher();
        //rep(i,1,len-1) printf("%d ",p[i]-1);enter;
        //rep(i,1,len-1) printf("%d ",mr[i]);enter;
        //rep(i,1,len-1) printf("%d ",ml[i]);enter;
        rep(i,1,len) mr[i] = max(mr[i],mr[i-1]-1);
        per(i,len,1) ml[i] = max(ml[i],ml[i+1]-1);
        rep(i,1,len) ans = max(ans,ml[i] + mr[i]);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    可惜老板不看程序员写的书
    《让僵冷的翅膀飞起来》系列之四——Visitor模式之可行与不可爱
    《让僵冷的翅膀飞起来》系列之二——从实例谈Adapter模式
    策略模式的应用实践
    《让僵冷的翅膀飞起来》系列之三——从Adapter模式到Decorator模式
    用Design+Blend轻松制作环形文字
    silverlight3的"伪"3D续图片横向轮换
    silverlight.net官方网站图片切换源码
    css2.1中的属性选择器(css高手请绕道)
    多线程中的ManualResetEvent
  • 原文地址:https://www.cnblogs.com/captain1/p/9770079.html
Copyright © 2011-2022 走看看