后缀数组 倍增法模板

来源:互联网 发布:魔法王座神器7上8数据 编辑:程序博客网 时间:2024/05/01 19:19
string s, t;namespace sa {//倍增法求后缀数组 (nlogn)const int maxn = 1e5 + 5;int n, k;int sa[maxn], rank[maxn], tmp[maxn], lcp[maxn];bool cmp(int i, int j) {if (rank[i] != rank[j]) {return rank[i] < rank[j];}else {int ri = i + k <= n ? rank[i + k] : -1;int rj = j + k <= n ? rank[j + k] : -1;return ri < rj;}}void build(const string &s) {//build sa rankn = s.length();for (int i = 0; i <= n; ++i) {sa[i] = i;rank[i] = i < n ? s[i] : -1;}for (k = 1; k <= n; k <<= 1) {sort(sa, sa + n + 1, cmp);tmp[sa[0]] = 0;for (int i = 1; i <= n; ++i) {tmp[sa[i]] = tmp[sa[i - 1]] + cmp(sa[i - 1], sa[i]);}for (int i = 0; i <= n; ++i) {rank[i] = tmp[i];}}//build lcpint h = 0;lcp[0] = 0;for (int i = 0; i < n; ++i) {int j = sa[rank[i] - 1];if (h > 0) h--;for (; j + h < n && i + h < n; ++h) {if (s[j + h] != s[i + h]) break;}lcp[rank[i] - 1] = h;}}void print() {printf("%s \t %s \t %s \t %s \t %s\n","i", "sa[i]", "rank[sa[i]]", "lcp[i]", "s[sa[i]]");for (int i = 0; i <= n; ++i) {printf("%d \t %d \t %6d \t %d \t\t %s\n", i, sa[i], rank[sa[i]], lcp[i], s.substr(sa[i]).c_str());}}void debug() {s = "abracadabra";build(s);print();/*i        sa[i]   rank[sa[i]]     lcp[i]          s[sa[i]]0        11           0          01        10           1          1               a2        7            2          4               abra3        0            3          1               abracadabra4        3            4          1               acadabra5        5            5          0               adabra6        8            6          3               bra7        1            7          0               bracadabra8        4            8          0               cadabra9        6            9          0               dabra10       9           10          2               ra11       2           11          0               racadabra*/}}

原创粉丝点击