目录

字符串

CF802H

题意

构造两个字符串$s,p$,满足$s$有恰好$n$个子序列等于$p$,要求两者长度均不超过$200$。$(n \le 10^6)$

题解

当$n=1$时,$s=a,p=a$满足条件,当$n=2$时,$s=abb,p=ab$满足条件。
我们设$t$为形如$abcd \cdots$的字符串,并保证任何时刻两字符串均满足$s=tu,p=t$,其中$u$可为空。显然$n=1,2$的解满足该条件。
设$t$尾部字符的下一个字母为$x$。
考虑$n\rightarrow2n+1$的变换,,$s=txuxx,p=tx$即满足条件,其中$tx$贡献一个子序列,而$tu$中有$n$个$t$的子序列,因此$tuxx$贡献$2n$个子序列。
同理有$n\rightarrow2n+2$的变换,,$s=txxuxx,p=tx$,证明同上。
根据这个变换即可以$n=1$或$n=2$为起点,构造出符合条件的长度为$O(\log n)$的字符串。

CF1393E2

题意

给出$n$个字符串,对每个字符串,可以删除其任意一个字符或让其保持原样,求最后使得字符串字典序不降的方案数,对$10^9+7$取模。$(1 \le n \le 10^5, \sum|s_i| \le 10^6)$

题解

本题的难点在于对于一个字符串删去至多一个字符后得到的数个字符串的排序问题。设字符串长度为$L$,我们可以利用如下的算法在$O(L)$完成。

设第$i$个字符右边第一个与$s_i$不同的字符为$nxt_i$,如果没有令$nxt_i=z$。维护两个指针$l=1,r=L$,从左到右依次考虑每个字符,如果$s_i>nxt_i$,那么删去第$i$个字符后得到的字符串排序后在第$l$个位置,并令$l++$;否则删去第$i$个字符后得到的字符串排序后在第$r$个位置,并令$r--$。原字符串所在位置位于删去最后一个字符所得到字符串的后面。

简要证明:如果$s_i>nxt_i$,那么删掉后面的字符都会比删掉这个字符先碰到一个更大的,因此当前字符就是最小的,反之亦然。

之后我们可以维护对于每一个字符串排序过后的序列,以每一种结尾的合法序列有多少个,因为我们已经排序过,所以转移时可以利用双指针进行快速转移,我们再写一个稍微特殊一点的哈希用于比较两个至多删去/没删字符串的大小即可。总复杂度$O(L \log L)$,注意string的最后一位并不一定是'\0',对于长度过长的边界情况,要直接特判。