zoukankan      html  css  js  c++  java
  • [NOI2018]你的名字

    题目描述

    (A) 被选为了 (ION2018) 的出题人,他精心准备了一道质量十分高的题目,且已经把除了题目命名以外的工作都做好了。

    由于 (ION) 已经举办了很多届,所以在题目命名上也是有规定的,(ION) 命题手册规定:每年由命题委员会规定一个小写字母字符串,我们称之为那一年的命名串,要求每道
    题的名字必须是那一年的命名串的一个非空连续子串,且不能和前一年的任何一道题目的名字相同。

    由于一些特殊的原因,小 (A) 不知道 (ION2017) 每道题的名字,但是他通过一些特殊手段得到了 (ION2017) 的命名串,现在小 (A)

    (Q) 次询问:每次给定 (ION2017) 的命名串和 (ION2018) 的命名串,求有几种题目的命名,使得这个名字一定满足命题委员会的规定,即是 (ION2018) 的命名串的一个非
    空连续子串且一定不会和 (ION2017) 的任何一道题目的名字相同。

    由于一些特殊原因,所有询问给出的 (ION2017) 的命名串都是某个串的连续子串,详细可见输入格式。

    先考虑 (l=1,r=|S|) 的情况 ((68pts))

    我们可以对 (S) 建出 (SAM),把 (T) 扔到上面跑匹配得到数组 (L)

    如果不考虑本质不同这一限制,那么答案就是 (sumlimits_{i=1}^{|T|}i-L[i])

    然后考虑怎么去重,我们同时对 (T) 建出 (SAM),同时对每个点处理出 (pos[i]),即该状态第一次出现位置

    那么每个点对答案的贡献就是 (sumlimits_{i=1}^{tot}len[i]-max(len[f[i]],L[pos[i]]))

    然后考虑任意区间的情况 ((100pts))

    发现我们需要快速得到一个区间的 (SAM),然而并没有什么好的方法

    再仔细想想,我们真的一定要得到这段区间的 (SAM) 吗?

    其实我们只需要借助 (SAM) 求出 (L) 数组

    而观察 (l=1,r=|S|) 的情况,对于 ([l,r]) 我们需要以下几种操作

    • 1.查询点 (x) 在 [l,r] 内是否有 (c) 这个转移

    • 2.跳 (parent)

    • 3.得到一个节点的 (len)

    发现其实在 ([1,|S|])(SAM) 上也可以实现这些操作,主要问题在于怎么查询点 (x) 在 [l,r] 内是否有 (c) 这个转移

    发现这本质上是求点 (ch[x][c])(endpos) 集合中是否有 ([l+length,r]) 之间的点

    处理一下 (endpos) 集合就可以查询了

    还有就是我们跳 (parent) 前应该先减小 (length) 查询是否匹配

    总复杂度 (O(|S|log|S|+sumlimits_{i=1}^Q |T_i|log|T_i|))

  • 相关阅读:
    JDK8新特性
    控制线程同步的方法
    Java面向对象(一)20170517
    Java语言基础-递归
    勒索病毒应对措施
    JAVA application 初步20170515
    JAVA语言基础(二)20170511
    JAVA语言基础(二)20170510
    JAVA学习概述(一)20170508
    我有一个读绘本的妈妈
  • 原文地址:https://www.cnblogs.com/mikufun-hzoi-cpp/p/12100104.html
Copyright © 2011-2022 走看看