时间安排
7:30–7:50 读题,T1构造,T2是个找性质字符串题,T3估计是个神秘 dp 。
7:50–8:30 T1,显然有一个分治的做法,写完发现是 O(n) 的,而且没什么前途。没想到什么合适的构造。
8:30–9:30 T2,题意太复杂了,真要考虑后缀树形态什么的估计做不了,考虑能不能找性质简化下题意。如果要求后缀全部匹配 kmp 貌似就可以做,可是这还要考虑交叉点,那么就要考虑串和串之间最长公共前缀之类的,这个貌似没有什么可做的性质,而且还要面临区间求本质不同字串个数的问题。
9:30–10:50 T3,麻烦点在于要求数字间两两不同,考虑容斥什么的,发现一直假。
10:50–12:00 思考T1,T2。
回顾反思
T1:
先考虑只有对角线为 0 的情况,那么有一个更本质的表述:对于第 i 行第 j 列的格子,要求所有 i 和 j 不同格子都被取到,那么可以考虑二进制分组,枚举位,令该为为 0 的列和该位为 1 的行对应的格子被覆盖,反着再来一遍,就好了。操作次数 2log 。
先考虑 j<=i<=j+1 的格子为 0 怎么做,发现可以考虑奇偶性,将奇数行和偶数行拆开,分别拼成两部分,将本质相同的列合并,那么就变成两个只有对角线为 0 的问题了,操作次数 4log 。
那么进一步,根据套路,可以重定义标号,比如取所有13位且有6位为1的二进制数作为标号,
C
(
13
,
6
)
>
n
2
C(13,6)>\frac{n}{2}
C(13,6)>2n 是够的,且这样的话对于每个子问题只用做一遍,比如只用考虑行对应位为1且列对应位为0.这样解决两个子问题是 2*13 约为 2log 。
T2:
主要考察的是 sam 与 后缀树 的性质。
题目实际要求后缀树上每条边对应串的本质不同子串数量和。
对于部分分:
对于原串 S ,其反串 sam 的 parent 树上儿子与父亲相差的串对应后缀树上某条边对应的串。
可以找到对应的区间,看做若干个询问,然后就是询问区间本质不同子串问题,可以 lca+sam 做。
区间本质不同子串个数
对于正解:
建立正串 sam 。
后缀树上任何一条边对应的串都能对应到 sam dag 图上某条路径。
更进一步的,将后缀树上所有关键点映射到 sam 的 dag 上标注出来,那么 sam 的 dag 上任意相邻关键点之间若干条边对应的串都能对应到后缀树上某条边的串,且后缀树上某条边的串都能对应到 sam 上某两相邻关键点中间的一段。对于 sam 中这样的一段,设两端点中在 dag 上为祖先的那个点为 x ,那么
l
e
n
[
x
]
−
l
e
n
[
f
a
[
x
]
]
len[x]-len[fa[x]]
len[x]−len[fa[x]] 就是这一段串对应到后缀树上相应位置出现的系数(对于同一个串,sam 上可能有多个这样的段,其系数总和就是后缀树上这个串出现的总次数)。
实际上,依我之见, sam 的 dag 图实际上能拆成后缀树, sam dag 图的结构变化后和后缀树完全一样。
那么我们就可以快速找到所有需要计算子串个数的串,换言之,问题变为, sam 上有若干这样的段,要求所有这样的段对应的串的 [本质不同子串个数*这个段的系数] 之和,由于显然这些段将 sam 上每条边都覆盖了一次,总长度是 O(n) 级别的,于是对每个段暴力跑 sam 计算本质不同子串个数即可。
代码 校OJ submission/382919
主要还是对后缀树和 sam 的理解不够。这种性质什么的要多积累。
T3:
神秘多项式,过于复杂。
其部分分也没有给出做法。
暂时跳过。