SA & SAM
后缀数组SA \(sa[i]\) 与 \(rk[i]\) \(sa[i]\) 表示排名为 \(i\) 的后缀是哪一个(在原串中开头位置)。 \(rk[i]\) (或 \(rank[i]\) )表示开头位置是 \(i\) 的后缀的排名。 两者是互相映射关系,即 \(sa[rk[i]] = i\) 。 后缀排序(倍增) 假设我们求出了只考虑长度为 \(w\) 的每一个后缀的前缀的 \(sa\) 和 \(rk\) ,怎么求考虑长度为 \(2w\) 的每一个后缀的前缀的 \(sa\) 和 \(rk\) . 对于两个后缀 \(i\) 和 \(j\) , 由于我们求出了在 \(w\) 下的 $sa $ 和 \(rk\) ,实际上可以通过比较两个二元组 \((rk_i,rk_{i+w}),(rk_j, rk_{j+w})\) 来确定大小关系,这里定义一个后缀 \(i\) 的两维度:第一维字符串 \([i...i+w-1]\) ,第二维字符串 \([i+w,i+2w-1]\) 。 为了方便实现以及减小常数,我们开一个辅助数组 \(tmp[i]\) 表示上一轮排序(长度 \(w\) ),排名为 \(i\) 的后缀的长度为 \(w\) 的前缀对应的是现在的哪一个后缀的第二维, \(tmp\) 可以由 \(w\) 下的 \(sa\) 求得。 cnt = 0; for (int i = n - w + 1