Luogu P4022 [CTSC2012]熟悉的文章

广义 \(SAM\) + 二分答案 + 单调队列优化 \(DP\)

对作文库建广义 \(SAM\) ,然后求出作文每个位置的最长匹配 \(d[i]\),然后二分答案 \(md\),然后 \(DP\) ,\(f[i]\) 表示到 \(i\) 的最大匹配长度,有 \(f[i]=\max(f[j]-j+i),j\in[i-d[i],i-md]\),最后检查 \(f[n]\geq 0.9\times len\)

#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=2000010;
int n,m;
int d[N],f[N],q[N];
char s[N];
struct SAM {
  int tot,lst,fa[N],c[N][2],len[N];
  SAM() {tot=lst=1;}
  inline void add(int ch) {
    if(c[lst][ch]&&len[c[lst][ch]]==len[lst]+1)
      return lst=c[lst][ch],void();
    R p=lst,np=++tot,q,nq,flg=0;
    len[np]=len[p]+1;
    while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
    if(!p) fa[np]=1;
    else {
      q=c[p][ch];
      if(len[q]==len[p]+1) fa[np]=q;
      else {
        if(p==lst) flg=1;
        nq=++tot;
        memcpy(c[nq],c[q],8);
        fa[nq]=fa[q],len[nq]=len[p]+1;
        fa[np]=fa[q]=nq;
        while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
      }
    } lst=flg?nq:np;
  }
  inline void calc() {
    R n=strlen(s+1),p=1,l=0;
    for(R i=1;i<=n;++i) {
      R ch=s[i]-48;
      while(p&&!c[p][ch]) p=fa[p],l=len[p];
      if(p) p=c[p][ch],++l;
      else p=1,l=0;
      d[i]=l;
    }
  }
}s1;
inline bool ck(int md) {
  R h=1,t=0,n=strlen(s+1);
  memset(f,0,md<<2);
  for(R i=md;i<=n;++i) {
    f[i]=f[i-1];
    while(h<=t&&f[q[t]]-q[t]<=f[i-md]-(i-md)) --t;
    q[++t]=i-md;
    while(h<=t&&q[h]<i-d[i]) ++h;
    if(h<=t) f[i]=max(f[i],i+f[q[h]]-q[h]);
  } return f[n]*10>=n*9;
}
inline void main() {
  m=g(),n=g();
  for(R i=1,len;i<=n;++i) { s1.lst=1;
    scanf("%s",s+1),len=strlen(s+1);
    for(R i=1;i<=len;++i) s1.add(s[i]-48);
  }
  for(R i=1;i<=m;++i) {
    scanf("%s",s+1);
    R l=0,r=strlen(s+1),md;
    s1.calc();
    while(l<r) {
      md=(l+r+1)>>1;
      if(ck(md)) l=md;
      else r=md-1;
    } printf("%d\n",l);
  }
}
} signed main() {Luitaryi::main(); return 0;}


2020.01.10

原文地址:https://www.cnblogs.com/Jackpei/p/12177446.html

时间: 2024-10-04 23:58:58

Luogu P4022 [CTSC2012]熟悉的文章的相关文章

P4022 [CTSC2012]熟悉的文章

P4022 [CTSC2012]熟悉的文章 题目大意 $m$个文本,$n$个模式串 对于每个模式串: 求最大L使得该串能分解成不小于$L$的子串,且在文本中出现的长度不小于该串总长度的$90%$ 建广义后缀树 对于$L_1$,$L_2$两种情况,$L_1>L_2$,如果$L_1$符合,显然$L_2$一定符合 发现没有,答案是单调的,用二分$check$ $dp_i$为前$i$个字符能匹配的最大长度 $dp_i=max\{dp[j]+i-j\}$转换后$dp_i=max\{(dp[j]-j)+i\

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

bzoj luogu 题目描述 阿米巴是小强的好朋友. 在小强眼中,阿米巴是一个作文成绩很高的文艺青年.为了获取考试作文的真谛,小强向阿米巴求教.阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范文拼拼凑凑而成的.小强不禁向阿米巴投去了疑惑的眼光,却发现阿米巴露出了一个狡黠的微笑. 为了有说服力地向阿米巴展示阿米巴的作文是多么让人觉得"眼熟",小强想出了一个评定作文 "熟悉程度"的量化指标\(L_0\).小强首先将作文转化成一个01串.之后

bzoj 2806: [Ctsc2012]Cheat 熟悉的文章

[题意] [题解] fhq自己写的题解就很清楚啦 (里面有关于神秘的阿米巴同学的介绍哦!很帅的样子,,, 我再来理一下思路 这道题思路应该是很简单很常规的,,但我做题太少辣! 二分一下肯定是必要的, 下面是判断是否可行的问题. 容易想到 要开一个 f 数组 表示 扫到了 第 i 位时 能匹配上多少个字母, 最后答案就是 f[lenth] * 10 >= lenth * 9 啦 f[i] 显然可以 通过 f[j] 转移 (j <= i - 二分出的下限的长度 + 1  且s[j……i]出现在字典

Luogu P2482 [SDOI2010]猪国杀

Pig Country Kill 很古怪的翻译,不过它确实叫猪(Pig)国(Country)杀(Kill). 我们来好好整理一下这道题目.题面虽较长,但内容基本清晰,只是有部分很Pig的操作部分,很容易让第一次看见这道题目的人百思不得其解. 先整理一下这道长长的题面. First:人物 四位玩家,初始四张手牌,血量上限\(4\),初始血量\(4\),会告诉你整个牌堆的牌,每位玩家每个回合从牌堆顶部抽走两张牌,放在自己手牌的右侧.人物分主猪,忠猪,和反猪,主猪只有一只,反猪和忠猪可以有多只,反猪全

Luogu P2014 选课

题面 对于这道题,我们考虑在树形dp上套背包.我们会非常自然的采用dfs扫描整棵树,然后对树上的每个节点都进行一次背包. 计\(dp[i][j]\)为在以第\(i\)号节点为根结点的子树中,用题目中选法选取\(j\)项的最大值. 我们在dfs的过程中,采用递归的方式,在子节点都处理完之后,便考虑将所有子节点的答案综合,得到当前节点的答案. 很显然,就是在容量为\(j\)的01背包中放下\(i\)节点的所有子节点背包中的答案,我们很容易想到下面的DP方程 \[f[x][j]=max(f[to][k

Luogu P5735 距离函数

题面 这只是道水水的入门题. 平面直角坐标系中两点间距离为 \[dis=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\] 所以三角形的周长就是 \[C=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}+\sqrt{(x_1-x_3)^2+(y_1-y_3)^2}+\sqrt{(x_2-x_3)^2+(y_2-y_3)^2}\] 在比赛中这道题的测试数据仿佛更改过,包括连样例也更改了,原来的题面要求是最多保留两位小数.就是说如果是个整数,不用输出小数部分:如果是一位小数

整理阅读的论文(三)

数学之所以有高声誉,其中一个理由就是数学使得自然科学实现定理化,给予自然科学某种程度的可靠性.                                                                                                                                                                        --阿尔伯特·爱因斯坦 网格优化已经被讨论了很多,这篇文章的主要亮点在

【转载】支持向量机(五)SMO算法

支持向量机(五)SMO算法 11 SMO优化算法(Sequential minimal optimization) SMO算法由Microsoft Research的John C. Platt在1998年提出,并成为最快的二次规划优化算法,特别针对线性SVM和数据稀疏时性能更优.关于SMO最好的资料就是他本人写的<Sequential Minimal Optimization A Fast Algorithm for Training Support Vector Machines>了. 我拜

Windows Azure Service Bus (4) Service Bus Queue和Storage Queue的区别

<Windows Azure Platform 系列文章目录> 熟悉笔者文章的读者都了解,Azure提供两种不同方式的Queue消息队列: 1.Azure Storage Queue 具体可以参考:       Windows Azure Cloud Service (12) PaaS之Web Role, Worker Role, Azure Storage Queue(下) Azure Storage Queue提供基础的消息队列服务,例如AddMessage, DeleteMessage.