[POJ 1743]

Musical Theme

后缀数组。

这两天都在研究罗穗骞神牛的《后缀数组——处理字符串的有力工具》,很久以前就听过的数据结构,现在总算用到了。

题意是给出一个长20000的数组,值范围是1到88,问是否存在长度大于等于5的一个子串,其满足“变调”后非重叠地出现在原数组的其他位置。这里变调的意思是整个子串同时加上或减去某个值。

分析题意后可以发现,如果取值间的差值建立一个新数组,那么新数组上长度为m的非重叠重复出现的子串对应着原数组中长度为m+1的子串。这样就解决了“变调”的问题。

进一步分析,可以发现可以二分答案:对于某个值l,当m<=l时满足题意的子串总存在。从而将问题转化为判定性问题。 然后对每次枚举的m值,使用后缀数组建立的height[],便可O(n)地判断是否可行了。 不过由于建立数组时我只实现了基于快排的二倍增,因此总体复杂度被拖低成O(n(lgn)^2)了,g++下跑了610ms。

另外,这题之前也已经用字符串hash做过了的(半年前还在用数组实现hash表),竟然比后缀数组还要快些(g++ 438ms)……

ps: 又发现了一个很有趣的blog:Summer’s Mariner