bzoj

luogu

题目描述

阿米巴是小强的好朋友。

在小强眼中,阿米巴是一个作文成绩很高的文艺青年。为了获取考试作文的真谛,小强向阿米巴求教。阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范文拼拼凑凑而成的。小强不禁向阿米巴投去了疑惑的眼光,却发现阿米巴露出了一个狡黠的微笑。

为了有说服力地向阿米巴展示阿米巴的作文是多么让人觉得“眼熟”,小强想出了一个评定作文 “熟悉程度”的量化指标\(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\)值比其他同学的明显要大。请你帮他验证一下。

sol

显然\(L_0\)是可二分的吧。

那么我们二分出一个\(L\),对原序列做一遍\(check\)

发现这个玩意儿很像一个序列\(dp\)?

设\(f_i\)表示前\(i\)个位置能够匹配的最大长度。那么转移有:

\[f_i=max(f_j+i-j),i-j>=L且s[j+1..i]能够匹配
\]

这个是强制\(i\)在匹配里的,那么令\(f[i]=max(f[i],f[i-1])\)就可以满足设定了。

我们设\(pp[i]\)表示匹配到\(i\)位置时的最长匹配长度,那么\(s[j+1..i]\)能够匹配就当且仅当\(j>=i-pp[i]\)。显然\(i-pp[i]\)是单调的,所以我们可以维护一个\(i\)递增\(f[i]-i\)递减的单调队列,每次取队首元素更新\(dp\)值。

至于\(i-j>=L\)的限制,我们只要在计算\(f[i]\)之前,把\(i-L\)插入到单调队列里面去就行了。

复杂度变成了优秀的\(O(n\log{n})\)

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 2e6+5;
int n,m,l,last=1,tot=1,tr[N][2],fa[N],len[N],pp[N],q[N],dp[N];
char s[N];
void extend(int c)
{
int v=last,u=++tot;last=u;
len[u]=len[v]+1;
while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
if (!v) fa[u]=1;
else{
int x=tr[v][c];
if (len[x]==len[v]+1) fa[u]=x;
else{
int y=++tot;
memcpy(tr[y],tr[x],sizeof(tr[y]));
fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
}
}
}
bool check(int mid)
{
int hd=1,tl=0;
for (int i=1;i<=l;++i)
{
dp[i]=dp[i-1];
if (i<mid) continue;
while (hd<=tl&&dp[q[tl]]-q[tl]<=dp[i-mid]-i+mid) --tl;
q[++tl]=i-mid;
while (hd<=tl&&q[hd]<i-pp[i]) ++hd;
if (hd<=tl) dp[i]=max(dp[i],dp[q[hd]]+i-q[hd]);
}
return dp[l]*10>=l*9;
}
int main()
{
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%s",s+1);l=strlen(s+1);
last=1;
for (int i=1;i<=l;++i) extend(s[i]-'0');
}
while (n--)
{
scanf("%s",s+1);l=strlen(s+1);
for (int i=1,now=1,cnt=0;i<=l;++i)
{
int c=s[i]-'0';
if (tr[now][c]) ++cnt,now=tr[now][c];
else{
while (now&&!tr[now][c]) now=fa[now];
if (!now) cnt=0,now=1;
else cnt=len[now]+1,now=tr[now][c];
}
pp[i]=cnt;
}
int L=0,R=l;
while (L<R)
{
int mid=L+R+1>>1;
if (check(mid)) L=mid;
else R=mid-1;
}
printf("%d\n",L);
}
return 0;
}

[BZOJ2806][CTSC2012]熟悉的文章(Cheat)的更多相关文章

  1. P4022 [CTSC2012]熟悉的文章

    题目 P4022 [CTSC2012]熟悉的文章 题目大意:多个文本串,多个匹配串,我们求\(L\),\(L\)指(匹配串中\(≥L\)长度的子串出现在文本串才为"熟悉",使得匹配 ...

  2. [CTSC2012]熟悉的文章(后缀自动机+动态规划)

    题目描述 阿米巴是小强的好朋友. 在小强眼中,阿米巴是一个作文成绩很高的文艺青年.为了获取考试作文的真谛,小强向阿米巴求教.阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范 ...

  3. 【[CTSC2012]熟悉的文章】

    题目 好题啊 \(SAM\)+单调队列优化\(dp\) 首先这个\(L\)满足单调性真是非常显然我们可以直接二分 二分之后套一个\(dp\)就好了 设\(dp[i]\)表示到达\(i\)位置熟悉的文章 ...

  4. 题解-CTSC2012 熟悉的文章

    Problem bzoj 题目大意:给定多个标准串和一个文本串,全部为01串,如果一个串长度不少于\(L\)且是任意一个标准串的子串,那么它是"熟悉"的.对于文本串\(A\),把\ ...

  5. CTSC2012 熟悉的文章

    传送门 首先很容易想到对于所有的模式串建出广义后缀自动机,之后对于我们每一个要检查的文本串,先在SAM上跑,计算出来每一个位置能匹配到的最远的位置是多少.(就是当前点减去匹配长度) 之后--考虑DP- ...

  6. Luogu4022 CTSC2012 熟悉的文章 广义SAM、二分答案、单调队列

    传送门 先将所有模板串扔进广义SAM.发现作文的\(L0\)具有单调性,即\(L0\)更小不会影响答案,所以二分答案. 假设当前二分的值为\(mid\),将当前的作文放到广义SAM上匹配. 设对于第\ ...

  7. [CTSC2012]熟悉的文章 (后缀自动机 单调队列)

    /* 首先答案显然是具有单调性的, 所以可以二分进行判断 然后当我们二分过后考虑dp来求最长匹配个数, 发现每个点能够转移的地点 肯定是一段区间, 然后这样就能够得到一个log^2算法 至于每个点的匹 ...

  8. [CTSC2012]熟悉的文章 后缀自动机

    题面:洛谷 题解: 观察到L是可二分的,因此我们二分L,然后就只需要想办法判断这个L是否可行即可. 因为要尽量使L可行,因此我们需要求出对于给定L,这个串最多能匹配上多少字符. 如果我们可以对每个位置 ...

  9. Luogu-4022 [CTSC2012]熟悉的文章

    广义后缀自动机+DP 对于作文库建出广义后缀自动机,广义自动机就是在每次添加一个字符串之前把\(last=0\),然后正常添加就好了 对于每个询问串,预处理出每个位置\(i\)能向前匹配的最长长度\( ...

随机推荐

  1. 首页底部菜单FragmentTabHost的使用

    一般现在的菜单都是底部FragmentTabHost,切换Fragment来实现的,今天我们就使用这个来看看如何实现的 首先是布局文件 <?xml version="1.0" ...

  2. Jenkins maven仓库地址 和 手动修改maven 版本

    ① Jenkins maven仓库地址,一般情况会在:/root/.m2/repository/* ② 手动修改maven 版本,Apache 下载指定的maven版本,然后解压后copy到指定目录即 ...

  3. Orthogonal Least Squares Learning Algorithm for Radial Basis Function Networks

    Orthogonal Least Squares Learning Algorithm for Radial Basis Function Networks S. Chen, C. F. N. Cow ...

  4. kettle连接资源库设置

    到这里你是登陆不上去的,需要创建或更新按钮,因为需要在你的数据库里创建关于kettle的数据表,来存储资源库 点执行就可以了 一般情况下kettle资源库自动给你创建两个用户: 工具->资源库- ...

  5. dos与unix文件格式之间的转换

    1. VI编辑器中转换 在VI中使用命令 set ff?(fileformat)可以查看文件的格式,使用set ff=dos(unix)可以设置文件的格式 2.使用sed处理(来至http://www ...

  6. Python核心编程课后习题-第六章

    1. 字符串, string模块中是否有一种字符串方法或者函数可以帮我鉴定一下一个字符串是否是另一个大字符串的一部分? str1 = 'abcdefghijklmnopqrstuv' print st ...

  7. hd acm1005

    问题: 已知递推公式:f[i] = ( a * f[i-1] + b * f[i-2] ) % 7,f[1]=1,f[2]=1. 需要你输入三个数a,b,n.其中a,b用来补充上述公式,用补充后的公式 ...

  8. Android 4.4 U盘挂载【转】

    本文转载自:https://blog.csdn.net/mill_li/article/details/50134301 在Android4.4系统下,ES文件浏览器读取不到U盘,但是在设置-> ...

  9. RabbitMQ之Exchange

    交换机的作用: 生产者发送消息不会向传统方式直接将消息投递到队列中,而是先将消息投递到交换机中,在由交换机转发到具体的队列,队列在将消息以推送或者拉取方式给消费者进行消费,这和我们之前学习Nginx有 ...

  10. 阻挡ddos攻击的函数