zoukankan      html  css  js  c++  java
  • 【bzoj3790】神奇项链——manacher+贪心

    听说这道题可以用树状数组什么鬼的做,反正我不会,还是老老实实打manacher+贪心大法吧……

    我们只要在跑manacher的过程中,用一个结构体(也可以直接用数组)来记录以每个字符为对称轴的最长回文的最左端和最右端,然后就得到了一些线段,于是问题完美地转换成了求取最少段的线段来完全覆盖一个区间了,直接排完序后贪心一遍即可。当然这里面有些比较是不必要的,但我也懒得去优化了。

    具体实现细节看代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    char s[100010];
    int p[100010],pos,cnt;
    struct point
    {
        int begin,end;
    }a[100010];
    bool cmp(point b,point c)
    {
        return b.begin<c.begin||(b.begin==c.begin&&b.end>c.end);
    }
    int main()
    {
        while(~scanf("%s",s))
        {
            memset(p,0,sizeof(p));
            int len=strlen(s);
            pos=0;cnt=0;
            for(int i=len;i>=0;i--)
            {
                s[i*2+2]=s[i];
                s[i*2+1]='#';
            }
            s[0]='$';
            for(int i=2;i<len*2+1;i++)
            {
                if(pos+p[pos]>i)p[i]=min(p[pos*2-i],pos+p[pos]-i);
                else p[i]=1;
                while(s[i+p[i]]==s[i-p[i]])p[i]++;
                if(pos+p[pos]<i+p[i])pos=i;
                a[++cnt].begin=i-p[i]+1;a[cnt].end=i+p[i]-1;
            }
            sort(a+1,a+1+cnt,cmp);
            int ans=0,r=a[1].end,now=2;
            while(r<len*2)
            {
                int r0=r;
                while(now<=cnt&&a[now].begin<=r)
                {
                    r0=max(r0,a[now].end);
                    now++;
                }
                ans++;r=r0;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    树---对称的二叉树
    树---二叉树的下一个节点
    阿里一面电话面
    树---重建二叉树
    CVTE电话面
    聊聊平台型游戏
    Ogre-next with Visual Studio 2019, SDL Memset, CL.exe error
    中国能不能制作AAA游戏?
    Simple Cel Shading 钟馗
    Modeling -> Mixamo auto rigging -> UE4 retargeting
  • 原文地址:https://www.cnblogs.com/JKAI/p/6959643.html
Copyright © 2011-2022 走看看