• 【BZOJ2806】【CTSC2012】Cheat


    题意:

    Description

    Input

    第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数
    接下来M行的01串,表示标准作文库
    接下来N行的01串,表示N篇作文

    Output

    N行,每行一个整数,表示这篇作文的Lo 值。

    HINT

    输入文件不超过1100000字节

    注意:题目有改动,可识别的长度不小于90%即可,而不是大于90%

    题解:

    好题!

    先对标准作文库建出广义SAM,把每个作文串在SAM上匹配,求出每一位之前最长出现过子串长度$s[i]$;

    显然没有什么好办法直接求L,考虑二分答案判断是否可行;

    设当前二分值为$mid$,$f[i]$表示前$i$位最长的熟悉长度,则易得DP方程:$f[i]=max{f[j]+i-j}$,决策区间就是$[i-s[i],i-mid]$;

    显然$i-s[i]$单调不降,所以可以用单调队列优化到$O(n)$

    最后判一下比例是否大于$90\%$即可。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #define inf 2147483647
     8 #define eps 1e-9
     9 using namespace std;
    10 typedef long long ll;
    11 typedef double db;
    12 int n,m,l,r,ans,len,tot=1,last,rt=1,son[2200001][2],fa[2200001],mx[2200001],s[1100001],q[1100001],f[1100001];
    13 char st[1100001];
    14 void extend(int ch){
    15     int p=last,np=++tot;
    16     mx[np]=mx[p]+1;
    17     for(;p&&!son[p][ch];p=fa[p])son[p][ch]=np;
    18     if(!p)fa[np]=rt;
    19     else{
    20         int q=son[p][ch];
    21         if(mx[q]==mx[p]+1)fa[np]=q;
    22         else{
    23             int nq=++tot;
    24             mx[nq]=mx[p]+1;
    25             memcpy(son[nq],son[q],sizeof(son[q]));
    26             fa[nq]=fa[q];
    27             fa[q]=fa[np]=nq;
    28             for(;p&&son[p][ch]==q;p=fa[p])son[p][ch]=nq;
    29         }
    30     }
    31     last=np;
    32 }
    33 void pre(char *st,int len){
    34     int nw=rt,tmp=0;
    35     for(int i=1;i<=len;i++){
    36         if(son[nw][st[i]-'0']){
    37             nw=son[nw][st[i]-'0'];
    38             tmp++;
    39         }else{
    40             for(;nw&&!son[nw][st[i]-'0'];nw=fa[nw]);
    41             if(!nw){
    42                 nw=rt;
    43                 tmp=0;
    44             }else{
    45                 tmp=mx[nw]+1;
    46                 nw=son[nw][st[i]-'0'];
    47             }
    48         }
    49         s[i]=tmp;
    50     }
    51 }
    52 bool check(int k){
    53     int L=1,R=0;
    54     for(int i=1;i<=len;i++){
    55         f[i]=f[i-1];
    56         if(i<k)continue;
    57         for(;L<=R&&f[q[R]]-q[R]<f[i-k]-i+k;R--);
    58         q[++R]=i-k;
    59         for(;L<=R&&q[L]<i-s[i];L++);
    60         if(L<=R)f[i]=max(f[i],f[q[L]]-q[L]+i);
    61     }
    62     return f[len]*10>=len*9;
    63 }
    64 int main(){
    65     scanf("%d%d",&n,&m);
    66     for(int i=1;i<=m;i++){
    67         scanf("%s",st+1);
    68         len=strlen(st+1);
    69         last=rt;
    70         for(int j=1;j<=len;j++){
    71             extend(st[j]-'0');
    72         }
    73     }
    74     for(int i=1;i<=n;i++){
    75         scanf("%s",st+1);
    76         len=strlen(st+1);
    77         pre(st,len);
    78         l=ans=0,r=len;
    79         while(l<=r){
    80             int mid=(l+r)/2;
    81             if(check(mid))ans=mid,l=mid+1;
    82             else r=mid-1;
    83         }
    84         printf("%d
    ",ans);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    Thymeleaf介绍和基本语法使用
    2020版idea及没有default Settings设置的idea,修改默认maven设置、本地仓库的方法
    创建springboot项目的两种方式
    2020版IDEA新建打开*.vue文件
    IDEA新手常用快捷键
    搭建一个maven的web项目
    eclipse、idea引入外部jar包教程
    序列化笔记
    转换流笔记
    缓冲流笔记
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/10160110.html
Copyright © 2020-2023  润新知