首页 > 其他分享 >CF1483F Exam

CF1483F Exam

时间:2024-02-06 13:22:43浏览次数:28  
标签:子串 le Exam 后缀 ne 当且 CF1483F 字符串

我永远喜欢数据结构

神仙 \(\color{maroon} *3400\) 字符串题。感觉现有的一篇 SA 题解讲的不太清楚,来一篇更加清楚、严谨的 SA 题解。

洛谷 CF

  • 给出 \(n\) 个字符串 \(s_1\sim s_n\),求有多少对 \((i,j)\),满足:
    • \(1\le i,j\le n\)。
    • \(s_j\) 是 \(s_i\) 的子串。
    • 不存在 \(k\)(\(i,j,k\) 两两不同)使得 \(s_j\) 是 \(s_k\) 的真子串,且 \(s_k\) 是 \(s_i\) 的真子串。
  • \(n,\sum\limits_{i=1}^n|s_i|\le 10^6\)。若 \(i\ne j\),则 \(s_i\ne s_j\)。
  • \(\text{2 s / 512 MB}\)。

先将所有串拼成一个大串 \(S\) 进行后缀排序。考虑枚举 \(i\),求出哪些 \(j\) 会产生贡献。

考虑对于 \(s_i\) 的每个后缀 \(s_i[x,|s_i|]\),在 \(s_1\sim s_n\) 中,找到一个最长的字符串 \(s_y\),满足它是 \(s_i[x,|s_i|]\) 的前缀,记为 \(l_{i,x}=|s_y|\)。若找不到这样的 \(s_y\),则称 \(l_{i,x}\) 无意义。若某个 \(l_{i,x}\) 能出现在等式或不等式中进行运算,当且仅当 \(l_{i,x}\) 有意义。

构造一个二元组不可重集合 \(T_i\),一个二元组 \((u,v)\) 在 \(T_i\) 中出现,当且仅当满足以下四个条件:

  • \(1\le u,v\le |s_i|\)。
  • \(l_{i,u}\) 有意义。
  • \(v=u+l_{i,u}-1\)。
  • 不存在 \(w\in[1,u)\),使得 \(u+l_{i,u}-1\le w+l_{i,w}-1\)。

称 \(s_j\) 在 \(T_i\) 中出现,当且仅当存在 \((u,v)\in T_i\) 使得 \(s_i[u,v]=s_j\)。

再构造一个二元组不可重集合 \(R_{i,j}\),一个二元组 \((u,v)\) 在 \(R_{i,j}\) 中出现,当且仅当满足以下两个条件:

  • \(1\le u\le v\le |s_i|\)。
  • \(s_i[u,v]=s_j\)。

那么原题目中的二元组 \((i,j)\) 满足条件,当且仅当 \(\boldsymbol{R_{i,j}\ne \varnothing}\) 且 \(\boldsymbol{R_{i,j}\subseteq T_i}\)

\(R_{i,j}\ne \varnothing\) 很显然,就不证了。

证明:

  • 充分性:

    考虑反证,假设当 \(R_{i,j} \subseteq T_i\) 时存在 \(k\) 使得 \(s_j\) 是 \(s_k\) 的子串且 \(s_k\) 是 \(s_i\) 的真子串。

    设 \(s_i[a,b]=s_k\),\(s_k[c,d]=s_j\)。那么 \(s_i[a+c-1,a+d-1]=s_j\)。根据已知条件可以得到 \((a+c-1,a+d-1)\in R_{i,j},T_i\)。

    若 \(l_{i,a+c-1}\ne d-c+1\),则与 \((a+c-1,a+d-1)\in T_i\) 的第三个条件不符。

    否则,此时 \(c>1\)。根据 \(l_{i,a}\) 的定义可知 \(l_{i,a}\ge b-a+1\),即 \(a+l_{i,a}-1\ge b\)。但是 \(a+c-1+l_{i,a+c-1}-1=a+c-1+d-c+1-1=a+d-1\)。根据 \(d\le b-a+1\) 可以得到 \(a+d-1\le b\)。与 \((a+c-1,a+d-1)\in T_i\) 的第四个条件不符。

    因此假设不成立。当 \(R_{i,j} \subseteq T_i\) 时一定不存在 \(k\) 使得 \(s_j\) 是 \(s_k\) 的子串且 \(s_k\) 是 \(s_i\) 的真子串。

  • 必要性:

    考虑 \((u,v)\in R_{i,j}\) 但是 \((u,v)\notin T_i\)。此时 \((u,v)\) 一定满足某个二元组在 \(T_i\) 中的前两个条件。

    若 \(l_{i,u}\ne v-u+1\),则有一个更长的字符串 \(s_y\) 为 \(s_i[u,|s_i|]\) 的前缀。此时 \(s_j\) 为 \(s_y\) 的真子串。

    否则,一定存在 \(w\in[1,u)\) 使得 \(u+l_{i,u}-1\le w+l_{i,w}-1\)。说明存在一个字符串 \(s_y=s_i[w,w+l_{i,w}-1]\)。此时 \(s_y\) 把 \(s_j\) 包含在中间,即 \(s_j\) 是 \(s_y\) 的真子串(能保证是真子串是因为 \(w\in[1,u)\))。

    所以不满足 \(R_{i,j}\subseteq T_i\) 一定不会满足原来的条件,这是一个必要条件。

光有这个结论还不够,总不可能求出集合然后枚举判断。

进一步推理可以得到,它其实等价于 \(\boldsymbol{\sum\limits_{(u,v)\in T_i}P(s_i[u,v]=s_j)=|R_{i,j}|}\)。

为了区分中括号和艾弗森括号,使用 \(P(A)\) 表示 \(A\) 命题是否为真。当且仅当 \(A\) 为真命题时 \(P(A)=1\);当且仅当 \(A\) 为假命题时 \(P(A)=0\)。

为什么呢?不难发现 \(\sum\limits_{(u,v)\in T_i}P(s_i[u,v]=s_j)=|T_i\bigcap R_{i,j}|\le |R_{i,j}|\)。而 \(|T_i\bigcap R_{i,j}|=|R_{i,j}|\) 等价于 \(R_{i,j}\subseteq T_i\)。

那么我们只需要对于一个 \(j\),求出 \(\sum\limits_{(u,v)\in T_i}P(s_i[u,v]=s_j)\) 和 \(|R_{i,j}|\) 即可。

  • 前者的求法:

    首先要得到 \(T_i\)。可以考虑对于每个字符串 \(s_a\),它会对哪些排名的后缀的产生贡献。这个后缀要包含 \(s_a\),等价于两者 \(|\text{LCP}|\ge |s_a|\)。可以维护 \(\text{height}\) 数组的 ST 表然后二分得到排名区间,让这个区间内的 \(l\) 值对 \(|s_a|\) 取 \(\max\)。线段树维护即可。

    然后就可以从左往右扫,维护前缀的 \(u+l_{i,u}-1\le w+l_{i,w}-1\) 最大值 \(pre\)。在线段树上单点查询当前后缀排名那个位置的值得到 \(l_{i,x}\)。若 \(x+l_{i,x}-1>pre\),则将 \((x,x+l_{i,x}-1)\) 加入 \(T_i\)。

    然后使用桶维护 \(T_i\) 中 \(s_1\sim s_n\) 中每种字符串各作为多少个后缀的最长前缀。

  • 后者的求法:

    考虑 \(s_j\) 作为某个后缀的前缀出现,同样可以求出包含它的后缀排名区间。然后变成求区间内有多少个排名使得这个排名的后缀来自于编号为 \(i\) 的字符串。

    对于每个 \(i\) 用一个 vector 从小到大存放其后缀出现的位置,二分得到左右端点 \(l,r\),答案即为 \(r-l+1\)。

这样仍需要枚举 \(j\)。但你注意到:

由于 \(R_{i,j}\ne \varnothing\),那些没在 \(T_i\) 中出现的 \(s_j\) 一定没有贡献。因为此时 \(|T_i\bigcap R_{i,j}|=0< |R_{i,j}|\)。只需要考虑那些在 \(T_i\) 中出现的 \(s_j\)。而对于每个 \(u\),只会有一个 \(v\) 使得 \((u,v)\in T_i\),因此 \(|T_i|=\mathcal{O}(|s_i|)\)。这样一来总共只需要处理 \(\mathcal{O}(|S|)\) 次。

为了不算重算漏,考虑对于每个在 \(T_i\) 中出现的字符串,在其第一次出现的位置统计。

最后对 \(s_1\sim s_n\) 的每个字符串都这样做一遍,就能得到正确答案了。

时空复杂度均为 \(\mathcal{O}(|S|\log |S|)\)。常数巨大,喜提最劣解,空间还是压线过的。时间估计是拼接字符串自带 \(2\) 倍以及线段树的 \(4\) 倍导致的。空间的话估计是我线段树合并信息写法的问题,应该可以再省个十几 \(\text{MB}\)。被 ACAM 打爆了 /ll。

AC code

接下来是一点闲话:

这题原来叫 Exam 啊,我想起了我刚考完的期末考试。哎,输得一塌糊涂,就像 OI 一样失败。我这辈子赢不了,只能度过一个不玩原神的失败人生了呜呜 /ll。

标签:子串,le,Exam,后缀,ne,当且,CF1483F,字符串
From: https://www.cnblogs.com/MnZnOIerLzy/p/18009547

相关文章

  • [ABC238F] Two Exams 题解
    题目链接题意有\(N\)个人,有两个\(1\simN\)排列\(P,Q\),在其中选择\(K\)个数,要满足:如果\(P_x<P_y\)且\(Q_x<Q_y\)则不能选了\(y\)而不选\(x\)。思路首先按照\(P\)从小到大排序,这样的话只用考虑\(Q\)。设\(f_{i,j,k}\)表示从前\(i\)个数中选\(j\)个,其中......
  • Gym104270E Kawa Exam
    题意简述有\(n\)道题,每道题有\(10^5\)个选项,其中选项\(a_i\)是正确的。再给定\(m\)条限制\(u_i,v_i\),表示题目\(u_i,v_i\)必须要选择相同的选项。对于\(m\)条限制,求出若去掉这条限制,最多能回答多少问题。多组数据。\(n,m,a_i\le10^5,\sumn,\summ\le10^6\)。......
  • 题解 P7169 [eJOI2020 Day1] Exam
    传送门。题意有两个长度为\(N\)的数列\(A_i\),\(B_i\)。可以对\(A\)数组进行若干次操作,每次可以使\(A_i\)到\(A_j\)中的所有数变成期间的最大值,求最多能使多少个数满足要求。分析显然,要使我们的某一个\(A_x\)变成\(B_x\),至少会包含\(A_{L_x}\)或\(A_{R_x}\),\(L_......
  • Applied Statistics - 应用统计学习 - numpy array交换两行 ? How to Swap Two Rows in
    https://www.statology.org/qualitative-vs-quantitative-variables/https://www.statology.org/numpy-swap-rows/HowtoSwapTwoRowsinaNumPyArray(WithExample)YoucanusethefollowingbasicsyntaxtoswaptworowsinaNumPyarray:some_array[[0,3],:......
  • Dependency injection framework -- Decoupled packages example (multiple container
    Dependencyinjectionframeworkhttps://python-dependency-injector.ets-labs.org/index.htmlDependencyInjectorisadependencyinjectionframeworkforPython.Ithelpsimplementingthedependencyinjectionprinciple.KeyfeaturesoftheDependencyInjecto......
  • 记Redux下载后,运行examples/todos时,报错Error: error:0308010C:digital envelope rout
    1、Redux下载下载地址gitclonehttps://github.com/reactjs/redux.git进入examples/todos,下载依赖:npminstall2、问题复现及解决执行命令npmrunstart此时终端报错:Error:error:0308010C:digitalenveloperoutines::unsupported解决方法:打开package.json,修改......
  • Beyond Hello World, A Computer Vision Example
    BeyondHelloWorld,AComputerVisionExampledlaicourse/Course1-Part4-Lesson2-Notebook.ipynbatmaster·lmoroney/dlaicourse(github.com)StartCoding导入TensorFlowimporttensorflowastfprint(tf.__version__)从tf.keras数据集API中获取时尚......
  • 关于.UnsupportedClassVersionError: org/example/Merge has been compiled by a more
    问题描述之前我是改变了本机上面的JDK的版本17为8;然后这次我再次尝试MapReduce运行就报错了;尝试更改IDEA中的环境JDK为8,还是一直显示这个错误~~~问题解决根本问题在pom.xml文件这里,里面有定义我们使用的JDK的版本,只要将其中的17改为8,然后再运行,就没有问题啦!!......
  • 【题解】CF1891E - Brukhovich and Exams
    【题解】CF1891E-BrukhovichandExamshttps://www.luogu.com.cn/problem/CF1891E我们考虑把区间分段:若两个相邻的数不互素,中间分开;若两个相邻的数中有且仅有一个\(1\),中间分开。那么我们得到了两种区间:全\(1\)区间与无\(1\)区间。若两个相邻数在同一区间内,那么就在区间......
  • 神经网络入门篇:详解多样本向量化(Vectorizing across multiple examples)
    多样本向量化与上篇博客相联系的来理解逻辑回归是将各个训练样本组合成矩阵,对矩阵的各列进行计算。神经网络是通过对逻辑回归中的等式简单的变形,让神经网络计算出输出值。这种计算是所有的训练样本同时进行的,以下是实现它具体的步骤:图1.4.1上篇博客中得到的四个等式。它们......