zoukankan      html  css  js  c++  java
  • [bzoj2806][Ctsc2012]Cheat(后缀自动机(SAM)+二分答案+单调队列优化dp)

    [bzoj2806][Ctsc2012]Cheat(后缀自动机(SAM)+二分答案+单调队列优化dp)

    偷懒直接把bzoj的网页内容ctrlcv过来了

    2806: [Ctsc2012]Cheat

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 1943  Solved: 1004
    [Submit][Status][Discuss]

    Description

    Input

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

    Output

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

    Sample Input

    1 2
    10110
    000001110
    1011001100

    Sample Output

    4

    HINT

    输入文件不超过1100000字节

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


    所谓少于$1.1*10^6$就是总输入字符数少于这个数...

    果然CTSC出的题水平够高

    专门爆踩SAM只学了板子不懂各个元素含义和应用的菜鸡(像我这样的就是了)

    随便把模式串扔进广义SAM里

    答案L0具有单调性

    所以二分答案

    接下来考虑$O(n)$求出最长匹配长度

    $O(n)$的话...只能dp了啊

    在SAM上跑字符串匹配求出每一位的最长向前匹配长度$f[i]$

    用$dp[i]$表示到i位置匹配了多少字符

    之后有dp方程

    $dp[i]=max(dp[i-1],max(dp[j=(i-f[i]) to (i-L0)]+i-j))$

    对于$dp[j]-j$,$O(n^2)$单调队列优化变成$O(n)$

    本题完结

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 using std::queue;
      5 const int N=1100011;
      6 char sin[N];
      7 int nn,nm,n;
      8 template<typename tp>tp max(tp a,tp b){return a>b?a:b;}
      9 
     10 struct sam
     11 {
     12     int tranc[2],len,pre;
     13 }s[N<<1];
     14 
     15 struct Sakuya_Brando
     16 {
     17     int size,fin;
     18     Sakuya_Brando(){size=1;}
     19     void insert(int ch)
     20     {
     21         int npx,npy,lpx,lpy;
     22         if(s[fin].tranc[ch])
     23         {
     24             lpx=fin,lpy=s[fin].tranc[ch];
     25             if(s[lpy].len==s[lpx].len+1) fin=lpy;
     26             else
     27             {
     28                 npy=++size;
     29                 s[npy]=s[lpy];
     30                 s[npy].len=s[lpx].len+1;
     31                 s[lpy].pre=npy;
     32                 while(s[lpx].tranc[ch]==lpy)
     33                 {
     34                     s[lpx].tranc[ch]=npy;
     35                     lpx=s[lpx].pre;
     36                 }
     37                 fin=npy;
     38             }
     39             return;
     40         }
     41         npx=++size;
     42         s[npx].len=s[fin].len+1;
     43         for(lpx=fin;lpx&&!s[lpx].tranc[ch];lpx=s[lpx].pre) s[lpx].tranc[ch]=npx;
     44         if(!lpx) s[npx].pre=1;
     45         else
     46         {
     47             lpy=s[lpx].tranc[ch];
     48             if(s[lpy].len==s[lpx].len+1) s[npx].pre=lpy;
     49             else
     50             {
     51                 npy=++size;
     52                 s[npy]=s[lpy];
     53                 s[npy].len=s[lpx].len+1;
     54                 s[lpy].pre=s[npx].pre=npy;
     55                 while(s[lpx].tranc[ch]==lpy)
     56                 {
     57                     s[lpx].tranc[ch]=npy;
     58                     lpx=s[lpx].pre;
     59                 }
     60             }
     61         }
     62         fin=npx;
     63     }
     64     void ins(char *str,int len)
     65     {
     66         fin=1;
     67         len=strlen(str);
     68         for(int i=0;i<len;i++) insert(str[i]-'0');
     69     }
     70 }sakuya;
     71 
     72 int f[N];
     73 int dp[N];
     74 struct stack
     75 {
     76     int v,id;
     77     stack(){}
     78     stack(int a,int b){v=a,id=b;}
     79 }sta[N];
     80 int he,ta;
     81 
     82 void bao0(char *str,int len)
     83 {
     84     int px=1,tmp=0;
     85     for(int i=0;i<len;i++)
     86     {
     87         int ch=str[i]-'0';
     88         if(s[px].tranc[ch]) tmp++,px=s[px].tranc[ch];
     89         else
     90         {
     91             while(px&&!s[px].tranc[ch]) px=s[px].pre;
     92             if(!px) tmp=0,px=1;
     93             else tmp=s[px].len+1,px=s[px].tranc[ch];
     94         }
     95         f[i]=tmp;
     96     }
     97 }
     98 void noi(char *str,int len)
     99 {
    100     for(int i=0;i<len;i++) f[i]=0;
    101 }
    102 bool check(char *str,int ll,int len)
    103 {
    104     he=1,ta=0;
    105     int mxx=0;
    106     for(int i=ll,j=ll-1;j<len;i++,j++)
    107     {
    108         dp[i]=dp[i-1];
    109         while(he<=ta&&sta[he].id<i-f[j]) he++;
    110         while(he<=ta&&sta[ta].v<=dp[i-ll]-(i-ll)) ta--;
    111         sta[++ta]=stack(dp[i-ll]-(i-ll),i-ll);
    112         while(he<=ta&&sta[he].id<i-f[j]) he++;
    113         if(he<=ta) dp[i]=max(dp[i],i+sta[he].v);
    114     }
    115     mxx=dp[len];
    116     for(int i=0;i<=len;i++) dp[i]=0;
    117     if(mxx*10>=len*9) return 1;
    118     else return 0;
    119 }
    120 
    121 int main()
    122 {
    123     scanf("%d%d",&nn,&nm);
    124     for(int i=1;i<=nm;i++)
    125     {
    126         scanf("%s",sin);
    127         n=strlen(sin);
    128         sakuya.ins(sin,n);
    129     }
    130     for(int i=1;i<=nn;i++)
    131     {
    132         scanf("%s",sin);
    133         n=strlen(sin);
    134         bao0(sin,n);
    135         int l0=0,r0=n;
    136         while(l0<r0)
    137         {
    138             int mid=(l0+r0+1)>>1;
    139             if(check(sin,mid,n)) l0=mid;
    140             else r0=mid-1;
    141         }
    142         noi(sin,n);
    143         printf("%d
    ",l0);
    144     }
    145     return 0;
    146 }
  • 相关阅读:
    AspNet WebApi 中应用fo-dicom抛出异常:No codec registered for tranfer syntax:
    Codeforces Round #261 (Div. 2)459A. Pashmak and Garden(数学题)
    Android开发之使用Web Service进行网络编程
    线段树 + 扫描线加深具体解释
    对Shell几个冷知识的总结(IFS,数组,替换,分割,查找)
    lscript.ld 链接器脚本
    iOS 系统地图实现及定位
    Perl怎样过滤html标签
    hdu1213 How Many Tables(并查集)
    数据结构——链表
  • 原文地址:https://www.cnblogs.com/rikurika/p/10827970.html
Copyright © 2011-2022 走看看