【NOIP模拟】20/02/09

B Z O J 4504 BZOJ4504 K个串

  • 题解:考虑用数据结构维护以一个点为右端点时,每一个左端点的答案
    考虑新增一个数的贡献,就是对一个左端点的区间的区间加
    于是用主席树实现区间加,堆维护每一个右端点的最优答案
    取出最优答案后将那个位置改为 I N F -INF 即可

C o d e Code


B Z O J 4503 BZOJ4503 两个串

  • 题解: F F T FFT 实现通配符匹配,定义从 t t 开始匹配的权值为 i = 0 m 1 B i ( A i + t B i ) 2 \sum_{i=0}^{m-1}B_i*(A_{i+t}-B_i)^2
    通配符 B i B_i 的权值为 0, 注意一下下标处理,我用了 4 次 d f t dft ,2 次 i d f t idft ,感觉不是最优解法
    C o d e Code

B Z O J 4502 BZOJ4502

  • 题解:好题
    有两种思路,第一种是用总的减去重复的,第二种是钦定重复的只被统计一次,两种方法都可以成功
    建出 t r i e trie 树后前缀的总个数是结点数,那么不考虑重复就是结点数的平方
    在这里插入图片描述
    考虑去掉重复的,我一开始的想法是枚举绿色部分,因为绿色部分是 t r i e trie 树上的一个前缀,那么当前重复的就是以绿色部分为前缀的串个个数 * 以绿色部分为后缀的串的个数,但自己把自己 h a c k hack 掉了
    在这里插入图片描述
    如果有 3 个重复的串的话会被绿色枚举到 3 次,题解注意到了更巧妙的性质
    在这里插入图片描述
    紫色串是出现在前缀中的蓝色串的后缀,那么紫色串一定在蓝色串到根的 f a i l fail 链上
    考虑解决刚才减多了的问题,考虑应该被减几次
    在这里插入图片描述
    注意到紫色串和它的后缀又可以贡献一个重复串,那么一个串的被统计次数就是 f a i l fail 链上一段的点数,我们的策略就是对于每一对 ( i , f a i l i ) (i,fail_i) 减一次,就可以不重不漏,就是那个著名的 “ 点 - 边 = 1 ”
    这么做以后,我们就可以枚举一个蓝色串,找到其跳一个 f a i l fail 的紫色串,蓝色串向上跳紫色串的深度找到绿色串,统计绿色串作为多少个串的后缀,这个就是 f a i l fail 子树的 s i z e size
    于是我们可以对原题进行加强,变成 S 3 e 5 \sum |S|\le 3e5 ,通过倍增来跳做到 S l o g ( S ) \sum|S|log(|S|)
    C o d e Code

  • 解法 2:考虑让每一个串只被统计到一次,注意到一个串在 A C AC 自动机上匹配的路径是唯一的
    我们可以变成统计合法的路径条数。
    考虑什么样的路径是合法的,第一种是一直向下走一个前缀但这个前缀可以分解成两个前缀,这个可以用 f a i l fail 判,第二种是跳过 f a i l fail ,假设第一次跳 f a i l fail 后走了 k k 步,那么如果停下来的点深度 k \ge k 这个串就是合法的。
    同时注意到最后形成的串长不会超过 60 60 ,于是我们可以设计 d p dp d p i , j dp_{i,j} 表示第一次跳 f a i l fail 后走了 k k 步,到结点 j j 的合法方案,复杂度 O ( S 60 26 ) O(\sum|S|*60*26) ,如果按上面的方法加强就可以卡掉
    C o d e Code
    两种方法都值得推敲,是一道好题,考场上与第一种方法接近,但没有发现更多的性质

发布了634 篇原创文章 · 获赞 98 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/sslz_fsy/article/details/104235771