[CTSC2012]熟悉的文章(后缀自动机+动态规划)
题目描述
阿米巴是小强的好朋友。
在小强眼中,阿米巴是一个作文成绩很高的文艺青年。为了获取考试作文的真谛,小强向阿米巴求教。阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范文拼拼凑凑而成的。小强不禁向阿米巴投去了疑惑的眼光,却发现阿米巴露出了一个狡黠的微笑。
为了有说服力地向阿米巴展示阿米巴的作文是多么让人觉得“眼熟”,小强想出了一个评定作文 “熟悉程度”的量化指标:L 0 .小强首先将作文转化成一个 01 串。之后,小强搜集了各路名家的文章,同样分别转化成 01 串后,整理出一个包含了 M 个 01 串的“ 标准作文库 ”。
小强认为:如果一个 01 串长度不少于 L 且在 标准作文库 中的某个串里出现过(即,它是 标准作文库 的 某个串 的一个 连续子串 ),那么它是“ 熟悉 ”的。对于一篇作文(一个 01 串)A,如果能够把 A 分割成若干段子串,其中“ 熟悉 ” 的子串的 长度 总 和 不少于 A 总 长度的 90%,那么称 A 是 “ 熟悉的文章 ”。 L 0 是 能够让 A 成为 “ 熟悉的文章 ” 的 所有 L 的最大值 (如果不存在这样的 L,那么规定 L 0 =0)。
举个例子:
小强的作文库里包含了如下 2 个字符串:
10110
000001110
有一篇待考察的作文是:
1011001100
小强计算出这篇作文 L 的最大值是 4,因为待考察的作文可以视作'10110'+'0110'+'0',其中'10110'和'0110'被判定为 “ 熟悉 ” 的。而当 L = 5 或是更大的时候,不存在符合题意的分割方法。所以,这篇作文的 L 0 = 4。小强认为阿米巴作文的 L 0 值比其他同学的明显要大。请你帮他验证一下。
题解
我们可以对模式串建广义SAM,求出文本串的每个前缀与模式串的最长公共后缀。
这玩意有什么用?
再继续考虑,答案具有单调性,我们可以外面套个二分。
然后又转移方程
dp[i]=max(dp[i-1],dp[j]+i-j)(i-LCS<=j<=i-mid)
很明显,转移是一个区间,而且这个区间是向右滑动的,所以可以直接上单调队列。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2200009
using namespace std;
int l[N],last,len,ch[N][],cnt,fa[N],q[N],h,t,dp[N],g[N],le[N],n,m;
char s[N];
inline void insert(int x){
if(!ch[last][x]){
int p=last,np=++cnt;l[np]=l[p]+;last=np;
for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np;//??
if(!p)fa[np]=;
else{
int q=ch[p][x];
if(l[p]+==l[q])fa[np]=q;
else{
int nq=++cnt;l[nq]=l[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
}
}
}
else{
int p=last,q=ch[last][x];
if(l[p]+==l[q])last=q;
else {
int nq=++cnt;l[nq]=l[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];fa[q]=nq;//!!
for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
last=nq;
}
}
}
inline void ins(int x){
while(h<=t&&g[q[t]]<=g[x])t--;
q[++t]=x;
}
inline bool check(int mid,int n){
h=,t=;
for(int i=;i<=n;++i)g[i]=dp[i]=;
for(int i=;i<=n;++i){
dp[i]=dp[i-];
int ll=i-le[i],rr=i-mid;ll=min(ll,rr+);
if(rr>=)ins(rr);
while(h<=t&&q[h]<ll)h++;
if(h<=t)dp[i]=max(dp[i],g[q[h]]+i);
g[i]=dp[i]-i;
}
return *dp[n]>=*n;
}
int main(){
scanf("%d%d",&n,&m);cnt=;
for(int i=;i<=m;++i){
scanf("%s",s+);len=strlen(s+);last=;
for(int j=;j<=len;++j)insert(s[j]-'');
}
while(n--){
scanf("%s",s+);len=strlen(s+);
int now=;
for(int i=;i<=len;++i){
if(ch[now][s[i]-''])now=ch[now][s[i]-''],le[i]=le[i-]+;
else{
while(now&&!ch[now][s[i]-''])now=fa[now];
if(now)le[i]=l[now]+,now=ch[now][s[i]-''];else now=;
}
}
int L=,R=len,ans=;
while(L<=R){
int mid=(L+R)>>;
if(check(mid,len))ans=mid,L=mid+;else R=mid-;
}
printf("%d\n",ans);
}
return ;
}
[CTSC2012]熟悉的文章(后缀自动机+动态规划)的更多相关文章
- [CTSC2012]熟悉的文章 后缀自动机
题面:洛谷 题解: 观察到L是可二分的,因此我们二分L,然后就只需要想办法判断这个L是否可行即可. 因为要尽量使L可行,因此我们需要求出对于给定L,这个串最多能匹配上多少字符. 如果我们可以对每个位置 ...
- P4022 [CTSC2012]熟悉的文章
题目 P4022 [CTSC2012]熟悉的文章 题目大意:多个文本串,多个匹配串,我们求\(L\),\(L\)指(匹配串中\(≥L\)长度的子串出现在文本串才为"熟悉",使得匹配 ...
- [CTSC2012]熟悉的文章(广义后缀自动机+二分答案+单调队列优化DP)
我们对作文库建出广义后缀自动机.考虑用\(SAM\)处理出来一个数组\(mx[i]\),表示从作文的第\(i\)个位置向左最远在作文库中出现的子串的长度.这个东西可以在\(SAM\)上跑\(trans ...
- 题解-CTSC2012 熟悉的文章
Problem bzoj 题目大意:给定多个标准串和一个文本串,全部为01串,如果一个串长度不少于\(L\)且是任意一个标准串的子串,那么它是"熟悉"的.对于文本串\(A\),把\ ...
- CTSC2012 熟悉的文章
传送门 首先很容易想到对于所有的模式串建出广义后缀自动机,之后对于我们每一个要检查的文本串,先在SAM上跑,计算出来每一个位置能匹配到的最远的位置是多少.(就是当前点减去匹配长度) 之后--考虑DP- ...
- 【[CTSC2012]熟悉的文章】
题目 好题啊 \(SAM\)+单调队列优化\(dp\) 首先这个\(L\)满足单调性真是非常显然我们可以直接二分 二分之后套一个\(dp\)就好了 设\(dp[i]\)表示到达\(i\)位置熟悉的文章 ...
- Luogu-4022 [CTSC2012]熟悉的文章
广义后缀自动机+DP 对于作文库建出广义后缀自动机,广义自动机就是在每次添加一个字符串之前把\(last=0\),然后正常添加就好了 对于每个询问串,预处理出每个位置\(i\)能向前匹配的最长长度\( ...
- [BZOJ2806][CTSC2012]熟悉的文章(Cheat)
bzoj luogu 题目描述 阿米巴是小强的好朋友. 在小强眼中,阿米巴是一个作文成绩很高的文艺青年.为了获取考试作文的真谛,小强向阿米巴求教.阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么 ...
- 【BZOJ2806】【CTSC2012】Cheat 广义后缀自动机+二分+Dp
题目 题目在这里 思路&做法 我们先对标准作文库建广义后缀自动机. 然后对于每一篇阿米巴的作文, 我们首先把放到广义后缀自动机跑一遍, 对于每一个位置, 记录公共子串的长度\((\)即代码和下 ...
随机推荐
- JEECG SSO kisso
kisso: java 基于 Cookie 的 SSO 中间件 kisso https://gitee.com/baomidou/kisso kisso首页.文档和下载 - 基于 Cookie 的 S ...
- 理解npm、nvm、nodejs之间的关系
nvm nvm:nodeJs版本管理工具,管理nodejs版本和npm版本,使用nvm安装nodejs时会将npm一起安装下来 nodejs nodeJs: 一种高效的JavaScript运行环境 n ...
- 设计模式之原型模式(c++)
问题描述 看到这个模式,很容易想到小时候看的<西游记>,齐天大圣孙悟空发飙的时候可以通过自己头上的 3 根毛立马复制出来成千上万的孙悟空, 对付小妖怪很管用(数量最重要). Prototy ...
- 用Python来操作redis 以及在Django中使用redis
什么是Redis? Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure server). Redis的键值可以包 ...
- python爬虫之PyQuery的基本使用
PyQuery库也是一个非常强大又灵活的网页解析库,如果你有前端开发经验的,都应该接触过jQuery,那么PyQuery就是你非常绝佳的选择,PyQuery 是 Python 仿照 jQuery 的严 ...
- SQL Server2012数据库开启远程连接
在我们使用SQL Server数据库的时候很重要的一点就是开启数据库的远程连接,这是因为很多时候数据库部署在远程的服务器上会比较方便,而部署在客户端的话,由于客户端不固定,所以需要经常去部署,这样容易 ...
- 莫烦theano学习自修第一天【常量和矩阵的运算】
1. 代码实现如下: #!/usr/bin/env python #! _*_ coding:UTF-8 _*_ # 导入numpy模块,因为numpy是常用的计算模块 import numpy as ...
- Hibernate最佳实战
1:一对一,一对多,多对多双向管理必设mappedBy ,将关系交给乙方维护,不然的话会在双方都建立关系,比如一对一双向的时候双方都会保存对方的id外键管理 具体在项目中采用双向还是单项看实际情况. ...
- hdu-1358(kmp)
题意:给你一个长度为n的字符串,问你一共有多少Xi——从0开始到Xi的这段长度这个字符子串是循环串,并输出最多的循环节的次数: 解题思路:用kmp的next数组,我们从next数组的值中可以看出这个字 ...
- LAMP架构部署和动态网站环境的配置
实验环境: 操作系统:centos 7.5 服务器IP:192.168.10.5 运行用户:root 连接工具:xshell工具 web环境:Linux+apache+php+mariadb(LAMP ...