zoukankan      html  css  js  c++  java
  • BZOJ2806:[CTSC2012]Cheat(广义SAM,二分,DP)

    Description

    Input

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

    Output

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

    Sample Input

    1 2
    10110
    000001110
    1011001100

    Sample Output

    4

    HINT

    输入文件不超过1100000字节

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

    Solution

    首先把广义$SAM$建出来,然后考虑对于一个询问,

    我们可以把这个作文放到$SAM$上跑,就可以求得这个字符串的每个位置向前延伸仍然可以匹配的最大长度,记为$Len[i]$。

    因为直接求答案不好求,所以我们二分一个答案$lim$

    剩下的就是$DP$了。$f[i]$表示到第$i$个位置最多能匹配多少,转移显然。

    $f[i]=max(f[i-1]),sum_{j=lim}^{len} f[i-j]+j$。 单调队列优化一下即可。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (2200009)
     5 using namespace std;
     6 
     7 int n,m,len,Len[N],f[N],q[N];
     8 char s[N];
     9 
    10 struct SAM
    11 {
    12     int son[N][2],fa[N],step[N];
    13     int p,q,np,nq,last,cnt;
    14     SAM(){last=cnt=1;}
    15 
    16     void Insert(int x)
    17     {
    18         p=last; np=last=++cnt; step[np]=step[p]+1;
    19         while (p && !son[p][x]) son[p][x]=np,p=fa[p];
    20         if (!p) fa[np]=1;
    21         else
    22         {
    23             q=son[p][x];
    24             if (step[q]==step[p]+1) fa[np]=q;
    25             else
    26             {
    27                 nq=++cnt; step[nq]=step[p]+1;
    28                 memcpy(son[nq],son[q],sizeof(son[q]));
    29                 fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    30                 while (son[p][x]==q) son[p][x]=nq,p=fa[p];
    31             }
    32         }
    33     }
    34     void Find(char s[])
    35     {
    36         int now=1,len=0;
    37         for (int i=0,l=strlen(s); i<l; ++i)
    38         {
    39             int c=s[i]-'0';
    40             if (son[now][c]) ++len,now=son[now][c];
    41             else
    42             {
    43                 while (now && !son[now][c]) now=fa[now];
    44                 if (!now) len=0,now=1;
    45                 else len=step[now]+1,now=son[now][c];
    46             }
    47             Len[i+1]=len;
    48         }
    49     }
    50 }SAM;
    51 
    52 bool check(int lim)
    53 {
    54     int head=1,tail=0,len=strlen(s);
    55     for (int i=1; i<=len; ++i)
    56     {
    57         f[i]=f[i-1];
    58         if (i-lim<0) continue;
    59         while (head<=tail && f[q[tail]]-q[tail]<=f[i-lim]-i+lim) --tail;
    60         q[++tail]=i-lim;
    61         while (head<=tail && q[head]<i-Len[i]) ++head;
    62         if (head<=tail) f[i]=max(f[i],f[q[head]]+i-q[head]);
    63     }
    64     return f[len]*10>=len*9;
    65 }
    66 
    67 int main()
    68 {
    69     scanf("%d%d",&n,&m);
    70     for (int i=1; i<=m; ++i,SAM.last=1)
    71     {
    72         scanf("%s",s);
    73         for (int j=0,l=strlen(s); j<l; ++j)
    74             SAM.Insert(s[j]-'0');
    75     }
    76     for (int i=1; i<=n; ++i)
    77     {
    78         scanf("%s",s);
    79         SAM.Find(s);
    80         int l=1,r=strlen(s),ans=0;
    81         while (l<=r)
    82         {
    83             int mid=(l+r)>>1;
    84             if (check(mid)) ans=mid,l=mid+1;
    85             else r=mid-1;
    86         }
    87         printf("%d
    ",ans);
    88     }
    89 }
  • 相关阅读:
    java架构解密——实时动态aop
    guice基本使用,配置模块的两种方式(三)
    guice基本使用,三种注入方式(二)
    guice的基本使用(一)
    Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
    java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题
    java泛型(一)、泛型的基本介绍和使用
    java泛型学习(2)
    jquery,从后台查数据,给页面上添加树形。
    Java Annotation认知(包括框架图、详细介绍、示例说明)
  • 原文地址:https://www.cnblogs.com/refun/p/10021310.html
Copyright © 2011-2022 走看看