CodeChef | September Challenge 2013 | To Queue or not to Queue

题目大意:

两种操作:

对字符串s(初始为空串)

1: 在s末尾加一个小写字母

2:删除s的第一个元素(保证删除后s非空)

每完成一个操作,记sum[i]为当前s串的不同子串, 求sigma{sum[i]}

...比赛期间怎么也想不到做法...基本上乱七八糟的做法都想过...还是不会...

后来看了ACRush的代码,终于会了...


做法如下:

记串[i,n) 为suffix[i]

---------

以样例来演示:

8
+ a
+ b
+ a
+ a
-
-
-
+ a


得到串"abaaa"

求一次后缀数组,得到

a
aa
aaa
abaaa
baaa


当前s=0, t=-1


+ a

---------

s = 0, t = 0

加入suffix[0]

a | baaa  (0)   ( | 用来划分有效长度)


+ a

---------

s = 0, t = 1

加入suffix[1]

ab | aaa  (0)

b | aaa  (1)


+ a

---------

s = 0, t = 2

加入suffix[2]

a | aa (2)

aba | aa (0)

ba | aaa (1)


+ a 

---------

s = 0, t = 3

加入suffix[3]

a | a (3)

aa | a (2)

abaa | a (0)

baaa | a (1)


-

---------

s = 1, t = 3

删除suffix[0]

a | a (3)

aa | a (2)

baaa | a (1)


-

---------

s = 2, t = 3

删除suffix[1]

a | a (3)

aa | a (2)


-

---------

s = 3, t = 3

删除suffix[2]

a | a  (3)

+ a

---------

s = 3, t = 4

加入suffix[4]

a (4)

aa (3)


以上操作可以通过 set  + 链表实现

set<int>::iterator e = S.lower_bound(rank[g]);
if(e == S.begin()) pre = n;
else pre = sa[*(--e)];

那么现在要做的就是完成以上操作的同时得到不同子串个数。

记子串个数为cur

记与以前重复的串个数为over

记答案为ans


对于 + 操作

我们插入suffix[t]

那么

更新链表/set

over -= lcp(pre[t], next[t]);

over += lcp(pre[t], t)

over += lcp(t, next[t])

同时要注意。如果lcp(pre[t], t) 或者 lcp(t, next[t])大于suffix[t]的有效长度,则暂不插入。因为当前来说这个串及它后面的串都是重复串。

简单证明如下。suffix[t+1] 是 suffix[t]的子串, 现在suffix[t]是 某个串的子串, 则suffix[t+1]也是某个串的子串。

对于 - 操作

更新链表/set

over -= lcp(pre[t], t)

over -= lcp(t, next[t])

over += lcp(pre[t], next[t])

cur 可以通过简单计算得到

ans += cur - over


搞定~



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值