BZOJ 2754: [SCOI2012]喵星球上的点名

10 篇文章 0 订阅
5 篇文章 0 订阅

题目

2754: [SCOI2012]喵星球上的点名

题解

我觉得这题非常有趣了。

据说这题是大力瞎搞,比如说用后缀数组的瞎搞就是先二分一个和询问的LCP>=询问长度的后缀然后往两边扩展。其实就是暴力。想了想好像比较好卡。名字的字符串里全是a,然后点名全点单个a,这样每次都会遍历完整个后缀数组。感觉这样的数据不是应该早就被加进去了吗,,为啥BZOJ没有人吐槽,可能是因为大家都觉得,,这题只有乱搞啦?莫名想起某省某字符串题暴力比SA高的事情。

我一开始把题读错了,把题目中说的喵当成了后缀,也就是说如果有k个后缀与询问的字符串LCP>=询问长度(一下称这k个为合法后缀)那么我认为对于这个询问的答案是k,然后最后是对每个后缀输出统计次数,,这样会很好做。先来看这个读错的题怎么做。

给一个字符串S,q个询问串,对于每个询问,输出这个串在S中出现了多少次(可以重叠)并将所有出现的第一个位置(比如ab在aabab中,这个东西是2和4)权值+1,最后输出所有位置的权值。
( |S|<=100000q<=100000100000 )

我写完之后发现,如果离线(字符串也不经常加密的嘛),的话第一问就是AC自动机模板题了。第二问貌似不太好做。。

后缀数组就十分好做了。就每次二分找到合法后缀范围[l,r],r-l+1就是这个询问的ans,要+1的话就是区间修改了,数据结构搞一搞就完了。

假设询问长度为m,这个二分根据刘汝佳说可以通过RMQ优化到 O(nlogn) 预处理之后 O(logn+m) ,直接二分的话是 O(mlogn) 的,不过好像,,在这里实际上是差不多的.感觉其实在哪都差不多。因为开始要一个nlogn预处理,除非m的级别到 106 ,然后n比较小才行。具体方法我下一篇讲一讲,,有兴趣的同学可以看一看。

然后我以为我做出来了,然后我读错题了。mdzz。看到一篇blog里面讲了一下不用暴力来解决第一个问题。博主暂时没有想到第二个问题怎么做。我当时就来了兴趣想了几十分钟,然后瞎搞出了一个算法。

第一问根据那个博主的思路,主席树维护一下就好,我感觉是用主席树维护我下面将要说的那个pre数组,然后主席树query有多少个pre小于询问的左端点。

第二问。假设我们对于后缀数组每个位置处理一个pre数组表示后缀数组里前一个此喵(当前这个后缀的主人)的后缀的rank(不存在则为-1),那么找到一个后缀数组上的区间[l,r]的时候,对于这个区间内第一次出现的喵(即pre[i] < l的位置的主人)我们需要对它们累加贡献来回答第二个询问,那么我们先把这样的区间分成两个操作,第一个是在l位置的加入区间操作,一个是在r+1位置的删除区间操作,然后做完原题目中所有询问之后,从前到后遍历后缀数组,维护一个数组cnt[i]表示左端点为l的区间有多少个,那么在遍历到一个后缀x的时候,需要给x的主人累加 sigma(cnt[i]) (pre[x] < i)的贡献。类似于一个区间求和,加入删除区间都是单点修改。

讲道理我还没有写,,瞎搞算法我都还没有写(不过感觉写了也没啥意思啊)。不过感觉起来码量挺棒的。而且还不知道对不对。算一算时间复杂度

倍增SA O(nlogn)

对于每个询问二分并标记区间加入删除 O(mlogn) (这里 m<=105

从左到右,每个点执行{
加入删除区间,树状数组单点修改 O(logn) 这一步操作总数为 O(q) 级别
统计答案,树状数组区间求和 O(logn)
}

一共大概就是,, O(nlogn+mlogn+qlogn)

还没写代码,其实我觉得可能比暴力慢。验证正确性满足一下自己的心理就够了233.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值