【洛谷1117_BZOJ4650】[NOI2016] 优秀的拆分(哈希_后缀数组_RMQ)

本文详细介绍了如何利用哈希和后缀数组解决NOI2016的一道题目,提供了三种不同的解法,包括奇葩的哈希95分做法、O(nlog2n)哈希期望解法以及O(nlogn)后缀数组优秀解法,通过这些解法分析和代码展示,帮助读者理解如何高效地寻找字符串中的特定子串。
摘要由CSDN通过智能技术生成

题目:

洛谷1117

分析:

定义把我校某兔姓神犇Tzz和他的妹子拆分,为“优秀的拆分”

随便写个哈希就能有 95 95 95分的好成绩……

我的 95 95 95分做法比fei较chang奇葩,不想浪费时间的可以忽略解法一qwq

解法一:

n n n个vector记录对于每个点 i i i,哪些长度 l e n len len满足 i + 2 l e n ≤ n i+2len\leq n i+2lenn s t r [ i , i + l e n ) = s t r [ i + l e n , i + 2 l e n ) str[i, i+len)=str[i+len,i+2len) str[i,i+len)=str[i+len,i+2len)(即形如“ A A AA AA”)。然后,枚举开头 l l l和“ A A AA AA”的长度 l e n len len,这种情况下的的答案就是以 l + 2 l e n l+2len l+2len开头的“ A A AA AA”数量(即“ B B BB BB”)。

解法二:

这题哈希可以过的说qwq(虽然我惨遭卡常没过去)

预处理出以每个点开始和结尾的“ A A AA AA”的数量 s t [ i ] st[i] st[i] e d [ i ] ed[i] ed[i],那么答案就是 ∑ i = 1 l e n − 1 e d [ i − 1 ] s t [ i ] \sum\limits_{i=1}^{len-1}ed[i-1]st[i] i=1len1ed[i1]st[i]

暴力枚举一个 A A A的长度 l e n len len,然后每隔 l e n len len个点作一个标记,共 ⌈ n l e n ⌉ \lceil \frac {n}{len} \rceil lenn个。可以发现任意长为 2 l e n 2len 2len的“ A A AA AA”都会经过两个标记。枚举标记,计算相邻两标记 a a a b b b开头的后缀的 L C P LCP LCP(最长公共前缀)和两标记结尾的前缀的 L C S LCS LCS(最长公共后缀)。如果 L C P + L C S ≥ l e n LCP+LCS\geq len LCP+LCSlen则存在一个“ A A AA AA”串经过这两个标记,且这些串的起始位置是连续的。简单画个图就可以发现,它们的起始位置是 [ a − L C S + 1 , a + L C P − l e n ] [a-LCS+1,a+LCP-len] [aLCS+1,a+LCPlen]。(脑补一下,第一个 A A A的开头不能比 a − L C S + 1 a-LCS+1 aLCS+1小,第一个 A A A的结尾不能比 a + L C P − 1 a+LCP-1 a+LCP1大。)用差分解决区间修改。

L

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值