zoukankan      html  css  js  c++  java
  • 字符串乱写

    loj6158
    考虑在一个位置放上加号,(S=A+B)
    若末尾存在 (0) ,一定是说 (A) 的最后一个数字与 (B) 的最后一个数字相加为 (10)。(特别的,需要特判二者末尾均为 (0) 这个情况)
    对于进位的问题,其实就是要求 (A) 前面的数字与 (B) 前面的数字相加为 (9)
    可以把原串翻转一下,问题转化为每个后缀与构造出的新的前缀进行匹配。
    这个问题可以用 ex-kmp 算法在线性时间/空间内解决。
    另一个特殊情况是,若 (A,B) 串的长度有一些差距,可能导致短串匹配完了,长串可以继续进位(必然是连续的9).
    预处理出后面有多少连续的 (9) 即可。

    CF1131E String Multiplication
    其实只要维护出当前的乘积中,每个字符的最长连续段有多长。
    根据当前乘的串 是否全为同一个字符,最长字符前缀,最长字符后缀,串中最长连续段 这四个信息,即可进行转移。

    CF653F Paper task
    大家都知道怎么用后缀自动机求本质不同的子串数,因为已经出现过的子串一定是一段后缀。
    所以对于每个前缀节点,只需要统计 (len_p - len_{fail_p})
    用同样的办法,问题是当前节点和一段区间中形成的合法的括号序列个数。
    大家都做过CSP-S D1T2,其实我们只需要对于每个点找到最靠后的合法的位置,然后连上一条边。
    这样的话就会形成一个树形结构,只要倍增找到合法的区间,直接累计深度为答案即可。

    CF610E Alphabet Permutations
    结论是这样的:答案为相邻并且逆序的字符对个数 (+1)
    似乎还挺显然的,若相邻并且正序,显然可以直接用一个排列拼出来。
    若相邻并且逆序,答案至少 (+1),并且总存在这样的方案。
    只要写一个简单的区间赋值,下传标记的线段树即可做到 (O(n log(n) |sum|^2))

    CF741E Arpa’s abnormal DNA and Mehrdad’s deep interest
    进行一些求 (lcp) 的操作,然后我们可以通过分类讨论得到一个 (O(1)) 比较字典序的方法。
    (k) 的限制比较麻烦,考虑选择一个阈值 (B)
    对于 (k geq B),枚举每个循环节然后 (ST) 查询区间最小值。
    对于 (k < B),对于每个 (mod k) 的不同取值都做一个 (ST) 表,然后枚举题意中 (i mod k) 的取值即可。
    (B) 在取值为 (sqrt{frac{n}{log(n)}}) 时取到最优。

    CF914F Substrings in a String
    正规做法大概就是分块,每次重构块内的数据结构。
    这样就将原问题转化为 跨过关键点(分块的边界) 和 不跨过关键点的。
    后者直接用数据结构做了,前者随便写个 kmp 哈希之类的直接暴力复杂度就是对的。
    然而有更加简单的做法,只要开 (26) 个 bitset,维护这种字符的出现位置集合。
    询问的时候新开一个 bitset ,表示每个点开始的后缀是否与 (y) 匹配上。
    枚举 (y) 的每个字符,进行一下位运算操作即可维护出。
    对于 ([l,r]) 的限制,只要用 (geq l) 的答案减去 (geq r-|y|+2) 的答案就好了。

    CF862F Mahmoud and Ehab and the final stage
    首先我们知道区间的 (lcp) 等同于相邻两个的 (lcp)(min)
    (height) 这个玩意画到一个平面上,问题等价于求一个最大的矩形。
    仍然考虑选择一个阈值 (B),显然对于 (lcp > B),只会出现 (frac{len}{B}) 次。
    对于小于阈值的,用线段树做一个最大子段和。
    对于大于阈值的,每次暴力取出跑一个笛卡尔树。

    CF587F Duff is Mad
    考虑对原序列进行分块,预处理出一个数组 (s_{i,j}) 表示第 (i) 个块中字符串总共在第 (j) 个字符串中出现了多少次。
    枚举每个块,然后对这个块构建一个 (AC) 自动机,把每个串在上面跑一遍即可。
    对于散点,问题是一个字符串在另一个字符串中出现多少次。
    一个比较显然的处理方法就是弄一个广义 (SAM),然后在 (fail) 树上进行线段树合并即可。
    然而似乎更简单的做法是这样的:
    问题其实就是把区间中的串弄一个 (AC) 自动机出来,然后把 (s_k) 中的每个点对父链求和。
    把询问简单的拆成前缀和相减的形式,然后进行根号分治。
    对于长度大于根号的 (s_k),可以把 (s_k) 预先放上去,然后在 (fail) 树上统计子树和,对于右端点的拓展只要累计一下子树和。
    对于长度小于根号的 (s_k),可以暴力在 (AC) 自动机上查询父链,其实在进行修改的时候修改 (dfs) 序区间即可用树状数组维护。
    一个简单的优化方法就是用分块的根号平衡把 (log) 去掉。

    CF1110H Modest Substrings
    如果 (r-l) 很小,把 ([l,r]) 中的每个数都插到 (AC) 自动机上,然后在 (AC) 自动机上跑个 dp 就行了。
    对于一般的情况,可以利用数位 (dp) 的思想,只需要记录当前与 (l,r) 各自的匹配关系。
    如果在当前与 (l) 匹配的情况下选了一个较大的数,那么后面不管怎样选都是合法的。
    所以只需要处理出这样一个数组,(sum_{x,i}) 表示从节点 (x) 向后走 (i) 位总是合法的子串数。
    在 dp 的过程中使用 (sum) 数组的前缀和就可以进行转移。
    为了输出最小字典序方案,可以倒着进行这个 dp。

    loj6681

    luogu P4218

  • 相关阅读:
    关于Mobx中装饰器语法的环境配置
    关于Java单例模式中懒汉式和饿汉式的两种类创建方法
    Java学习笔记之异常处理
    create-react-app脚手架的安装和目录结构介绍
    关于win10下JDK环境变量的配置以及关于JDK的一些说明
    关于Android studio的安装和配置问题
    关于通过ServletContext获取数据出现的http500的错误的解决方案
    关于form表单提交到Servlet的时候出现tomcat启动错误的解决方法
    Android网络编程系列之Volley总结
    Android网络编程系列之HTTP协议原理总结
  • 原文地址:https://www.cnblogs.com/skyh/p/13195278.html
Copyright © 2011-2022 走看看