传送门

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

之后……考虑DP……一开始我的状态设错了,设成了当前位置的最大的L的值,这样我就不知道怎么转移了……

于是换一个思路。考虑到其实我们可以判定L是否成立,于是改为二分答案,那么这次我们就用\(dp[i]\)表示到当前串第i位,已经被匹配为“熟悉”的总字符串长度。这样到最后只要判断一下是否大于90%即可。那么我们就有dp方程:

\[dp[i] = max_{j = i-maxl}^{i-L}(dp[j] + i - j,dp[i-1])
\]

这个方程还是很好理解的w…… 不过这样朴素的做法是\(O(n^2logn)\)的,但是这个方程因为左右端点都是递增的,那么我们就可以用单调队列维护一下。

然后就是喜闻乐见的单调队列优化DP。复杂度\(O(nlogn)\)。

#include<bits/stdc++.h>
#define rep(i,a,n) for(register int i = a;i <= n;i++)
#define per(i,n,a) for(register int i = n;i >= a;i--)
#define enter putchar('\n')
using namespace std;
typedef long long ll;
const int M = 2000005; int n,m,maxl[M],dp[M],head,tail,q[M],d;
string s; struct Suffix
{
int last,cnt,ch[M<<1][2],fa[M<<1],l[M<<1];
void extend(int c)
{
int p = last,np = ++cnt;
l[np] = l[p] + 1,last = cnt;
while(p && !ch[p][c]) ch[p][c] = np,p = fa[p];
if(!p) {fa[np] = 1;return;}
int q = ch[p][c];
if(l[q] == l[p] + 1) fa[np] = q;
else
{
int nq = ++cnt;
l[nq] = l[p] + 1,ch[nq][0] = ch[q][0],ch[nq][1] = ch[q][1];
fa[nq] = fa[q],fa[np] = fa[q] = nq;
while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
}
}
void match(string s)
{
int k = s.length()-1,u = 1,len = 0;
rep(i,0,k)
{
int c = s[i] - '0';
while(u != 1 && !ch[u][c]) u = fa[u],len = l[u];
if(ch[u][c]) u = ch[u][c],len++;
maxl[i+1] = len;
}
}
}SAM; bool pd(int x)
{
rep(i,1,x-1) dp[i] = 0;
head = 1,tail = 0;
rep(i,x,d)
{
dp[i] = dp[i-1];
while(head <= tail && dp[q[tail]] - q[tail] <= dp[i-x] - i + x) tail--;
q[++tail] = i - x;
while(head <= tail && q[head] < i - maxl[i]) head++;
if(head <= tail) dp[i] = max(dp[q[head]] - q[head] + i,dp[i]);
}
//printf("%d %d\n",x,dp[d]);
return dp[d] * 10 >= d * 9;
} int main()
{
ios::sync_with_stdio(0);
cin >> n >> m;
SAM.cnt = 1;
rep(i,1,m)
{
SAM.last = 1;
cin >> s,d = s.length()-1;
rep(i,0,d) SAM.extend(s[i] - '0');
}
rep(i,1,n)
{
cin >> s,d = s.length();
SAM.match(s);
//rep(i,1,d) printf("%d ",maxl[i]);enter;
int L = 0,R = d;
while(L < R)
{
int mid = (L + R + 1) >> 1;
//printf("%d\n",mid);
if(pd(mid)) L = mid;
else R = mid - 1;
}
printf("%d\n",L);
}
return 0;
}

CTSC2012 熟悉的文章的更多相关文章

  1. P4022 [CTSC2012]熟悉的文章

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

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

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

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

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

  4. [BZOJ2806][CTSC2012]熟悉的文章(Cheat)

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

  5. 题解-CTSC2012 熟悉的文章

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

  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. MachineLearningInAction

    2017-01-07 20:14:45 前面两周主要都是在复习然后考试,每天其实过得也挺苦逼的.基本上项目和学习上的是都没有接触了:复习了随机过程和数字信号处理和信号检测和估值:主要都是复习一些理论上 ...

  2. Python3.2官方文档翻译--作用域和命名空间实例

    6.2.1 作用域和命名空间实例 以下的实例主要用来示范怎样引用不同的作用域和命名空间,keywordglobal和nonlocalru怎样影响变量绑定. 实例执行结果是: After local a ...

  3. UVA571 - Jugs(数论)

    UVA571 - Jugs(数论) 题目链接 题目大意:给你A和B的水杯.给你三种操作:fill X:把X杯里面加满水.empty X:把X杯中的水清空.pour X Y 把X的水倒入Y中直到一方满或 ...

  4. 怎样制作gif图片?怎样制作你项目的动态效果图到你的csdn?

    怎样制作gif图?怎样上传你项目的动态效果图到你的csdn? 这仅仅是笔者用的方法.有其它方法的欢迎分享. 一张或几张展示了你的项目的功能及效果的动态图放在博客文章开头会为你的文章润色不少. 相信非常 ...

  5. [ACM] hdu 1217 Arbitrage (bellman_ford最短路,推断是否有正权回路或Floyed)

    Arbitrage Problem Description Arbitrage is the use of discrepancies in currency exchange rates to tr ...

  6. iOS开发UI篇—懒载入

    iOS开发UI篇-懒载入 1.懒载入基本 懒载入--也称为延迟载入,即在须要的时候才载入(效率低,占用内存小).所谓懒载入,写的是其get方法. 注意:假设是懒载入的话则一定要注意先推断是否已经有了. ...

  7. Android——动画的分类

    Android包含三种动画:View Animation, Drawable Animation, Property Animation(Android 3.0新引入). 1.View Animati ...

  8. 怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优

     怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优 1>.这里简单举个样例来说明DBMS_SQLTUN ...

  9. jquery的一点点认识

    概述 JQuery是继prototype之后又一个优秀的Javascript库.它是轻量级的js库 .它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, O ...

  10. JavaScript插件编写指南

    在编写插件之前,大家要先了解做插件的几个要点: 插件需要满足的条件 一个可复用的插件需要满足以下条件: 插件自身的作用域与用户当前的作用域相互独立,也就是插件内部的私有变量不能影响使用者的环境变量: ...