zoukankan      html  css  js  c++  java
  • BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP

    先建出广义后缀自动机。

    然后跑出文章中每一个位置的最大匹配距离。

    然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离。

    显然可以二分$L$的取值。

    然后容易得到$DP$方程

    $f[i]=max(f[i-1],f[j]+i-j)(j<=i-L)$

    然后就发现$j$属于一个区间,然后就可以单调队列优化了。

    #include <map>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define maxn 2200005
     
    namespace SAM{
        int last,cnt,go[maxn][2],l[maxn],fa[maxn],n,m,q;
        int f[maxn],que[maxn],hd,tl,d[maxn];
        char s[maxn];
        void init(){last=cnt=1;}
        void add(int x)
        {
            int q,p=last;
            if (q=go[p][x])
            {
                if (l[q]==l[p]+1) last=q;
                else
                {
                    int nq=last=++cnt;
                    l[nq]=l[p]+1;
                    memcpy(go[nq],go[q],sizeof go[q]);
                    fa[nq]=fa[q];fa[q]=nq;
                    for (;go[p][x]==q&&p;p=fa[p]) go[p][x]=nq;
                    last=nq;
                }
            }
            else
            {
                int np=last=++cnt; l[np]=l[p]+1;
                for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
                if (!p) fa[np]=1;
                else
                {
                    q=go[p][x];
                    if (l[q]==l[p]+1) fa[np]=q;
                    else
                    {
                        int nq=++cnt;l[nq]=l[p]+1;
                        memcpy(go[nq],go[q],sizeof go[q]);
                        fa[nq]=fa[q];
                        fa[q]=fa[np]=nq;
                        for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    }
                }
            }
        }
        void ins()
        {
            last=1;
            scanf("%s",s+1); n=strlen(s+1);
            F(i,1,n) add(s[i]-'0');
        }
        bool check(int mid)
        {
            f[0]=0; tl=0;hd=1;
            F(i,1,n)
            {
                f[i]=f[i-1];int p=i-mid;
                if (p>=0)
                {
                    while (hd<=tl&&f[que[tl]]-que[tl]<f[i-mid]-p)tl--;
                    que[++tl]=p;
                }
                while (hd<=tl&&que[hd]<i-d[i]) hd++;
                if (hd<=tl) f[i]=max(f[i],f[que[hd]]+i-que[hd]);
            }
            if (f[n]*10>=n*9) return true;
            else return false;
        }
        void dp()
        {
            scanf("%s",s+1); n=strlen(s+1);
            memset(d,0,(n+1)*sizeof(int));
            int now=1,t=0;
            F(i,1,n)
            {
                if (go[now][s[i]-'0'])
                    now=go[now][s[i]-'0'],t++;
                else
                {
                    while (now&&!go[now][s[i]-'0']) now=fa[now];
                    if (!now) now=1,t=0;
                    else t=l[now]+1,now=go[now][s[i]-'0'];
                }
                d[i]=t;
            }
            int l=0,r=n;
            while (l<r)
            {
                int mid=(l+r)/2+1;
                if (check(mid)) l=mid;
                else r=mid-1;
            }
            printf("%d
    ",l);
        }
        void solve()
        {
            init();
            scanf("%d%d",&q,&m);
            F(i,1,m) ins();
            F(i,1,q) dp();
        }
    }
     
    int main()
    {
        using namespace SAM;
        solve();
    }
    

      

  • 相关阅读:
    How To Build CyanogenMod Android for smartphone
    CentOS安装Code::Blocks
    How to Dual boot Multiple ROMs on Your Android SmartPhone (Upto Five Roms)?
    Audacious——Linux音乐播放器
    How to Dual Boot Multiple ROMs on Your Android Phone
    Everything You Need to Know About Rooting Your Android Phone
    How to Flash a ROM to Your Android Phone
    什么是NANDroid,如何加载NANDroid备份?
    Have you considered compiled a batman-adv.ko for android?
    BATMAN—Better Approach To Mobile Adhoc Networking (B.A.T.M.A.N.)
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6776354.html
Copyright © 2011-2022 走看看