题意:造出一个字符串的后缀数组,将sa数组与height数组输出。
这道题当然是一道后缀数组的模板。但是为了更高的效率,我们不用倍增法,而是使用SAM造出后缀树,再用后缀树造出后缀数组。
关于后缀树的资料可以去网上找,在此不赘述。我们唯一需要知道的是,后缀树每一条边对应的字符串首字符都是互不相同的,仅仅依靠首字符就可以区别从一个节点伸出的所有边。
首先,由于原串的SAM的next链接就是反串的后缀树,于是我们将原串的反串插入SAM,这样造出的后缀树就是原串的后缀树了。但是这样造出的仅仅是只有点和边的空后缀树,我们需要在上面添加信息。
我们对于每个节点记录一个pos——代表其中最长串(反串前缀)在原串后缀中对应的首字符位置,方便以后造sa数组。我们还需要维护一个right数组,这个数组并不代表right集合。对于每个插入字符时为接纳新子串产生的节点(而非分裂出来的节点),其right值=自身max值。而对于分裂出来的节点,其right值=该轮新产生节点的max。
在造后缀树的时候,节点本身的right值-其next节点的max值=后缀树中next节点到该节点边的首字符在反串中的位置。更进一步地,将反串起始位置到该位置的子串翻转,就是这条边对应的字符串。其实这一点不难理解,结合一下定义就很容易明白,这里不多说了。
将反串中的位置对应到原串上,找到那个字符作为边的首字符,我们就可以区分每条边,也就可以按照字典序遍历后缀树,依照每个节点的pos造出后缀数组了。
上代码。