博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[bzoj2806][Ctsc2012]Cheat(后缀自动机(SAM)+二分答案+单调队列优化dp)
阅读量:7014 次
发布时间:2019-06-28

本文共 3186 字,大约阅读时间需要 10 分钟。

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

2806: [Ctsc2012]Cheat

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

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
2 #include
3 #include
4 using std::queue; 5 const int N=1100011; 6 char sin[N]; 7 int nn,nm,n; 8 template
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*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
>1;139 if(check(sin,mid,n)) l0=mid;140 else r0=mid-1;141 }142 noi(sin,n);143 printf("%d\n",l0);144 }145 return 0;146 }

转载于:https://www.cnblogs.com/rikurika/p/bzoj2806.html

你可能感兴趣的文章
005_控制器和动作
查看>>
[struts]数据标签的使用
查看>>
Nginx
查看>>
小KING教你做android项目(二)---实现登陆页面并跳转和简单的注册页面
查看>>
Paint.FontMetrics
查看>>
初步理解require.js模块化编程
查看>>
计算机网络(一)
查看>>
asyncsocket的用法
查看>>
【贪心】HDU 1257
查看>>
nodejs 解决跨域
查看>>
04 变量和参数介绍
查看>>
C# 关于LINQ基础随笔
查看>>
ASP.NET MVC 3 Razor 视图引擎 基本语法
查看>>
C# 关于XML的简单操作实例
查看>>
ggplot2:画世界地图和中国地图 合并数据 增添信息 标记
查看>>
火狐开发----Web开发者工具
查看>>
修改mysql表操作
查看>>
简单背包问题
查看>>
SPOJ Problem 4452:Simple Arithmetics II
查看>>
c# 使用 Tchart控件之数据绑定
查看>>