zoukankan      html  css  js  c++  java
  • 后缀数组 (SA)

    约定

    • 本文中字符串下标从1开始
    • 后缀(i)表示(s[idots n])

    简述

    后缀数组(Suffix Array)主要由两个数组组成:(sa)(rank)
    其中(sa_i)表示排名为(i)的后缀,(rank_i)表示后缀(i)的排名。其二者构成了双映射的关系,即:(sa_{rank_i}=i,rank_{sa_i}=i)
    由于我们知道子串可以视作某个后缀的前缀,所以有时会在字符串的题目中利用此性质用到后缀数组。

    (O(nlog^2n))解法

    若一次比较的复杂度是(O(1))的,显然直接可以利用(sort)获得(O(nlogn))的排序复杂度。但对于两个字符串无法实现比较的(O(1))。回想字符串的比较方式,先找到两者的(lcp)(最长公共前缀),再比较下一位的大小即可(下一位为空视为最小)。也就是说,只要有较为快速的方法找到(lcp),就可以快速地进行比较。此时可以利用二分的方法,用哈希值判断是否相等,(O(log n))地找到两者的(lcp)并实现大小的比较。于是整体的排序复杂度即为(O(nlog^2n))
    有可能遇上哈希冲突的问题,但此种方法胜在好写。

    (O(nlogn))解法

    这是一种基于倍增思想的做法。
    先对每个长度为1的子串(即每个字符)进行排序。
    当已知长度为(w)的所有子串排名情况时,对于长度为(2w)的所有子串,其比较就是一个双关键字的比较。即先比较长度为(w)的前缀,若相等再比较后缀。超出(n)的部分统一视为无穷小,不会影响原子串的大小判断。等到(w)足够大((ge n-1))时,由于(s[idots i+w])与后缀(i)的排名相同,最后得到的(sa_i)即为所求。
    假设每次对长度为(w)的排序都可以实现(O(n))的时间复杂度,则总体便可以达到(O(nlogn))。因为在此背景下值域为排名,与(n)同阶,可以直接采用内层套用计数排序基数排序实现(O(n))的排序。

  • 相关阅读:
    随想 20180517
    随想 20180516
    随想 20180514
    alpinelinux
    装系统时总是提示 保存分区表时出现错误(0000000001)函数不正确
    kindeditor在Firefoxt 和 Chrome 下不能取到值的解决方法
    浏览器兼容
    php生成随机密码的几种方法
    按钮效果
    linux下修改/dev/shm tmpfs文件系统大小
  • 原文地址:https://www.cnblogs.com/hkr04/p/Suffix-Array.html
Copyright © 2011-2022 走看看