#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
#define tget(i) ( (t[(i)/8]&mask[(i)%8]) ? 1 : 0 )
#define tset(i, b) t[(i)/8]=(b) ? (mask[(i)%8]|t[(i)/8]) : ((~mask[(i)%8])&t[(i)/8])
#define chr(i) (cs==sizeof(int)?((int*)s)[i]:((unsigned char *)s)[i])
#define isLMS(i) (i>0 && tget(i) && !tget(i-1))
// find the start or end of each bucket
void getBuckets(unsigned char *s, int *bkt, int n, int K, int cs, bool end) {
int i, sum = 0;
for (i = 0; i <= K; i++)
bkt[i] = 0; // clear all buckets
for (i = 0; i < n; i++)
bkt[chr(i)]++; // compute the size of each bucket
for (i = 0; i <= K; i++) {
sum += bkt[i];
bkt[i] = end ? sum : sum - bkt[i];
}
}
// compute SAl
void induceSAl(unsigned char *t, int *SA, unsigned char *s, int *bkt, int n, int K, int cs, bool end) {
int i, j;
getBuckets(s, bkt, n, K, cs, end); // find starts of buckets
for (i = 0; i < n; i++) {
j = SA[i] - 1;
if (j >= 0 && !tget(j))
SA[bkt[chr(j)]++] = j;
}
}
// compute SAs
void induceSAs(unsigned char *t, int *SA, unsigned char *s, int *bkt, int n, int K, int cs, bool end) {
int i, j;
getBuckets(s, bkt, n, K, cs, end); // find ends of buckets
for (i = n - 1; i >= 0; i--) {
j = SA[i] - 1;
if (j >= 0 && tget(j))
SA[--bkt[chr(j)]] = j;
}
}
// find the suffix array SA of s[0..n-1] in {1..K}^n
// require s[n-1]=0 (the sentinel!), n>=2
// use a working space (excluding s and SA) of at most 2.25n+O(1) for a constant alphabet
void SA_IS(unsigned char *s, int *SA, int n, int K, int cs) {
int i, j;
unsigned char *t = (unsigned char *) malloc(n / 8 + 1); // LS-type array in bits
// Classify the type of each character
tset(n-2, 0);
tset(n-1, 1); // the sentinel must be in s1, important!!!
for (i = n - 3; i >= 0; i--)
tset(i, (chr(i)<chr(i+1) || (chr(i)==chr(i+1) && tget(i+1)==1))?1:0);
// stage 1: reduce the problem by at least 1/2
// sort all the S-substrings
int *bkt = (int *) malloc(sizeof(int) * (K + 1)); // bucket array
getBuckets(s, bkt, n, K, cs, true); // find ends of buckets
for (i = 0; i < n; i++)
SA[i] = -1;
for (i = 1; i < n; i++)
if (isLMS(i))
SA[--bkt[chr(i)]] = i;
induceSAl(t, SA, s, bkt, n, K, cs, false);
induceSAs(t, SA, s, bkt, n, K, cs, true);
free(bkt);
// compact all the sorted substrings into the first n1 items of SA
// 2*n1 must be not larger than n (proveable)
int n1 = 0;
for (i = 0; i < n; i++)
if (isLMS(SA[i]))
SA[n1++] = SA[i];
// find the lexicographic names of all substrings
for (i = n1; i < n; i++)
SA[i] = -1; // init the name array buffer
int name = 0, prev = -1;
for (i = 0; i < n1; i++) {
int pos = SA[i];
bool diff = false;
for (int d = 0; d < n; d++)
if (prev == -1 || chr(pos+d) != chr(prev+d) || tget(pos+d) != tget(prev+d)) {
diff = true;
break;
} else if (d > 0 && (isLMS(pos+d) || isLMS(prev+d)))
break;
if (diff) {
name++;
prev = pos;
}
pos = (pos % 2 == 0) ? pos / 2 : (pos - 1) / 2;
SA[n1 + pos] = name - 1;
}
for (i = n - 1, j = n - 1; i >= n1; i--)
if (SA[i] >= 0)
SA[j--] = SA[i];
// stage 2: solve the reduced problem
// recurse if names are not yet unique
int *SA1 = SA, *s1 = SA + n - n1;
if (name < n1)
SA_IS((unsigned char*) s1, SA1, n1, name - 1, sizeof(int));
else
// generate the suffix array of s1 directly
for (i = 0; i < n1; i++)
SA1[s1[i]] = i;
// stage 3: induce the result for the original problem
bkt = (int *) malloc(sizeof(int) * (K + 1)); // bucket array
// put all left-most S characters into their buckets
getBuckets(s, bkt, n, K, cs, true); // find ends of buckets
for (i = 1, j = 0; i < n; i++)
if (isLMS(i))
s1[j++] = i; // get p1
for (i = 0; i < n1; i++)
SA1[i] = s1[SA1[i]]; // get index in s
for (i = n1; i < n; i++)
SA[i] = -1; // init SA[n1..n-1]
for (i = n1 - 1; i >= 0; i--) {
j = SA[i];
SA[i] = -1;
SA[--bkt[chr(j)]] = j;
}
induceSAl(t, SA, s, bkt, n, K, cs, false);
induceSAs(t, SA, s, bkt, n, K, cs, true);
free(bkt);
free(t);
}
const int maxn = 200000;
int sa[maxn];
int lcp[maxn];
int _rank[maxn];
unsigned char *s;
int n;
void calc_lcp() {
for (int i = 0; i < n; i++)
_rank[sa[i]] = i;
for (int i = 0, h = 0; i < n; i++) {
if (_rank[i] < n - 1) {
for (int j = sa[_rank[i] + 1]; s[i + h] == s[j + h]; ++h)
;
lcp[_rank[i]] = h;
if (h > 0)
--h;
}
}
}
int main() {
string str = "CCCCC";
n = str.size();
s = (unsigned char*) str.c_str();
SA_IS(s, sa, n + 1, 256, 1);
calc_lcp();
for (int i = 0; i < n; i++) {
cout << str.substr(sa[i + 1]);
if (i < n - 1)
cout << " " << lcp[i + 1];
cout << endl;
}
}
I2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDxpb3N0cmVhbT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnVuc2lnbmVkIGNoYXIgbWFza1tdID0geyAweDgwLCAweDQwLCAweDIwLCAweDEwLCAweDA4LCAweDA0LCAweDAyLCAweDAxIH07CiNkZWZpbmUgdGdldChpKSAoICh0WyhpKS84XSZtYXNrWyhpKSU4XSkgPyAxIDogMCApCiNkZWZpbmUgdHNldChpLCBiKSB0WyhpKS84XT0oYikgPyAobWFza1soaSklOF18dFsoaSkvOF0pIDogKCh+bWFza1soaSklOF0pJnRbKGkpLzhdKQojZGVmaW5lIGNocihpKSAoY3M9PXNpemVvZihpbnQpPygoaW50KilzKVtpXTooKHVuc2lnbmVkIGNoYXIgKilzKVtpXSkKI2RlZmluZSBpc0xNUyhpKSAoaT4wICYmIHRnZXQoaSkgJiYgIXRnZXQoaS0xKSkKCi8vIGZpbmQgdGhlIHN0YXJ0IG9yIGVuZCBvZiBlYWNoIGJ1Y2tldAp2b2lkIGdldEJ1Y2tldHModW5zaWduZWQgY2hhciAqcywgaW50ICpia3QsIGludCBuLCBpbnQgSywgaW50IGNzLCBib29sIGVuZCkgewogICAgaW50IGksIHN1bSA9IDA7CiAgICBmb3IgKGkgPSAwOyBpIDw9IEs7IGkrKykKICAgICAgICBia3RbaV0gPSAwOyAvLyBjbGVhciBhbGwgYnVja2V0cwogICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBia3RbY2hyKGkpXSsrOyAvLyBjb21wdXRlIHRoZSBzaXplIG9mIGVhY2ggYnVja2V0CiAgICBmb3IgKGkgPSAwOyBpIDw9IEs7IGkrKykgewogICAgICAgIHN1bSArPSBia3RbaV07CiAgICAgICAgYmt0W2ldID0gZW5kID8gc3VtIDogc3VtIC0gYmt0W2ldOwogICAgfQp9Ci8vIGNvbXB1dGUgU0FsCnZvaWQgaW5kdWNlU0FsKHVuc2lnbmVkIGNoYXIgKnQsIGludCAqU0EsIHVuc2lnbmVkIGNoYXIgKnMsIGludCAqYmt0LCBpbnQgbiwgaW50IEssIGludCBjcywgYm9vbCBlbmQpIHsKICAgIGludCBpLCBqOwogICAgZ2V0QnVja2V0cyhzLCBia3QsIG4sIEssIGNzLCBlbmQpOyAvLyBmaW5kIHN0YXJ0cyBvZiBidWNrZXRzCiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgaiA9IFNBW2ldIC0gMTsKICAgICAgICBpZiAoaiA+PSAwICYmICF0Z2V0KGopKQogICAgICAgICAgICBTQVtia3RbY2hyKGopXSsrXSA9IGo7CiAgICB9Cn0KLy8gY29tcHV0ZSBTQXMKdm9pZCBpbmR1Y2VTQXModW5zaWduZWQgY2hhciAqdCwgaW50ICpTQSwgdW5zaWduZWQgY2hhciAqcywgaW50ICpia3QsIGludCBuLCBpbnQgSywgaW50IGNzLCBib29sIGVuZCkgewogICAgaW50IGksIGo7CiAgICBnZXRCdWNrZXRzKHMsIGJrdCwgbiwgSywgY3MsIGVuZCk7IC8vIGZpbmQgZW5kcyBvZiBidWNrZXRzCiAgICBmb3IgKGkgPSBuIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgICBqID0gU0FbaV0gLSAxOwogICAgICAgIGlmIChqID49IDAgJiYgdGdldChqKSkKICAgICAgICAgICAgU0FbLS1ia3RbY2hyKGopXV0gPSBqOwogICAgfQp9CgovLyBmaW5kIHRoZSBzdWZmaXggYXJyYXkgU0Egb2Ygc1swLi5uLTFdIGluIHsxLi5LfV5uCi8vIHJlcXVpcmUgc1tuLTFdPTAgKHRoZSBzZW50aW5lbCEpLCBuPj0yCi8vIHVzZSBhIHdvcmtpbmcgc3BhY2UgKGV4Y2x1ZGluZyBzIGFuZCBTQSkgb2YgYXQgbW9zdCAyLjI1bitPKDEpIGZvciBhIGNvbnN0YW50IGFscGhhYmV0CnZvaWQgU0FfSVModW5zaWduZWQgY2hhciAqcywgaW50ICpTQSwgaW50IG4sIGludCBLLCBpbnQgY3MpIHsKICAgIGludCBpLCBqOwogICAgdW5zaWduZWQgY2hhciAqdCA9ICh1bnNpZ25lZCBjaGFyICopIG1hbGxvYyhuIC8gOCArIDEpOyAvLyBMUy10eXBlIGFycmF5IGluIGJpdHMKICAgIC8vIENsYXNzaWZ5IHRoZSB0eXBlIG9mIGVhY2ggY2hhcmFjdGVyCiAgICB0c2V0KG4tMiwgMCk7CiAgICB0c2V0KG4tMSwgMSk7IC8vIHRoZSBzZW50aW5lbCBtdXN0IGJlIGluIHMxLCBpbXBvcnRhbnQhISEKICAgIGZvciAoaSA9IG4gLSAzOyBpID49IDA7IGktLSkKICAgICAgICB0c2V0KGksIChjaHIoaSk8Y2hyKGkrMSkgfHwgKGNocihpKT09Y2hyKGkrMSkgJiYgdGdldChpKzEpPT0xKSk/MTowKTsKICAgIC8vIHN0YWdlIDE6IHJlZHVjZSB0aGUgcHJvYmxlbSBieSBhdCBsZWFzdCAxLzIKICAgIC8vIHNvcnQgYWxsIHRoZSBTLXN1YnN0cmluZ3MKICAgIGludCAqYmt0ID0gKGludCAqKSBtYWxsb2Moc2l6ZW9mKGludCkgKiAoSyArIDEpKTsgLy8gYnVja2V0IGFycmF5CiAgICBnZXRCdWNrZXRzKHMsIGJrdCwgbiwgSywgY3MsIHRydWUpOyAvLyBmaW5kIGVuZHMgb2YgYnVja2V0cwogICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBTQVtpXSA9IC0xOwogICAgZm9yIChpID0gMTsgaSA8IG47IGkrKykKICAgICAgICBpZiAoaXNMTVMoaSkpCiAgICAgICAgICAgIFNBWy0tYmt0W2NocihpKV1dID0gaTsKICAgIGluZHVjZVNBbCh0LCBTQSwgcywgYmt0LCBuLCBLLCBjcywgZmFsc2UpOwogICAgaW5kdWNlU0FzKHQsIFNBLCBzLCBia3QsIG4sIEssIGNzLCB0cnVlKTsKICAgIGZyZWUoYmt0KTsKICAgIC8vIGNvbXBhY3QgYWxsIHRoZSBzb3J0ZWQgc3Vic3RyaW5ncyBpbnRvIHRoZSBmaXJzdCBuMSBpdGVtcyBvZiBTQQogICAgLy8gMipuMSBtdXN0IGJlIG5vdCBsYXJnZXIgdGhhbiBuIChwcm92ZWFibGUpCiAgICBpbnQgbjEgPSAwOwogICAgZm9yIChpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBpZiAoaXNMTVMoU0FbaV0pKQogICAgICAgICAgICBTQVtuMSsrXSA9IFNBW2ldOwogICAgLy8gZmluZCB0aGUgbGV4aWNvZ3JhcGhpYyBuYW1lcyBvZiBhbGwgc3Vic3RyaW5ncwogICAgZm9yIChpID0gbjE7IGkgPCBuOyBpKyspCiAgICAgICAgU0FbaV0gPSAtMTsgLy8gaW5pdCB0aGUgbmFtZSBhcnJheSBidWZmZXIKICAgIGludCBuYW1lID0gMCwgcHJldiA9IC0xOwogICAgZm9yIChpID0gMDsgaSA8IG4xOyBpKyspIHsKICAgICAgICBpbnQgcG9zID0gU0FbaV07CiAgICAgICAgYm9vbCBkaWZmID0gZmFsc2U7CiAgICAgICAgZm9yIChpbnQgZCA9IDA7IGQgPCBuOyBkKyspCiAgICAgICAgICAgIGlmIChwcmV2ID09IC0xIHx8IGNocihwb3MrZCkgIT0gY2hyKHByZXYrZCkgfHwgdGdldChwb3MrZCkgIT0gdGdldChwcmV2K2QpKSB7CiAgICAgICAgICAgICAgICBkaWZmID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9IGVsc2UgaWYgKGQgPiAwICYmIChpc0xNUyhwb3MrZCkgfHwgaXNMTVMocHJlditkKSkpCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICBpZiAoZGlmZikgewogICAgICAgICAgICBuYW1lKys7CiAgICAgICAgICAgIHByZXYgPSBwb3M7CiAgICAgICAgfQogICAgICAgIHBvcyA9IChwb3MgJSAyID09IDApID8gcG9zIC8gMiA6IChwb3MgLSAxKSAvIDI7CiAgICAgICAgU0FbbjEgKyBwb3NdID0gbmFtZSAtIDE7CiAgICB9CiAgICBmb3IgKGkgPSBuIC0gMSwgaiA9IG4gLSAxOyBpID49IG4xOyBpLS0pCiAgICAgICAgaWYgKFNBW2ldID49IDApCiAgICAgICAgICAgIFNBW2otLV0gPSBTQVtpXTsKICAgIC8vIHN0YWdlIDI6IHNvbHZlIHRoZSByZWR1Y2VkIHByb2JsZW0KICAgIC8vIHJlY3Vyc2UgaWYgbmFtZXMgYXJlIG5vdCB5ZXQgdW5pcXVlCiAgICBpbnQgKlNBMSA9IFNBLCAqczEgPSBTQSArIG4gLSBuMTsKICAgIGlmIChuYW1lIDwgbjEpCiAgICAgICAgU0FfSVMoKHVuc2lnbmVkIGNoYXIqKSBzMSwgU0ExLCBuMSwgbmFtZSAtIDEsIHNpemVvZihpbnQpKTsKICAgIGVsc2UKICAgICAgICAvLyBnZW5lcmF0ZSB0aGUgc3VmZml4IGFycmF5IG9mIHMxIGRpcmVjdGx5CiAgICAgICAgZm9yIChpID0gMDsgaSA8IG4xOyBpKyspCiAgICAgICAgICAgIFNBMVtzMVtpXV0gPSBpOwogICAgLy8gc3RhZ2UgMzogaW5kdWNlIHRoZSByZXN1bHQgZm9yIHRoZSBvcmlnaW5hbCBwcm9ibGVtCiAgICBia3QgPSAoaW50ICopIG1hbGxvYyhzaXplb2YoaW50KSAqIChLICsgMSkpOyAvLyBidWNrZXQgYXJyYXkKICAgIC8vIHB1dCBhbGwgbGVmdC1tb3N0IFMgY2hhcmFjdGVycyBpbnRvIHRoZWlyIGJ1Y2tldHMKICAgIGdldEJ1Y2tldHMocywgYmt0LCBuLCBLLCBjcywgdHJ1ZSk7IC8vIGZpbmQgZW5kcyBvZiBidWNrZXRzCiAgICBmb3IgKGkgPSAxLCBqID0gMDsgaSA8IG47IGkrKykKICAgICAgICBpZiAoaXNMTVMoaSkpCiAgICAgICAgICAgIHMxW2orK10gPSBpOyAvLyBnZXQgcDEKICAgIGZvciAoaSA9IDA7IGkgPCBuMTsgaSsrKQogICAgICAgIFNBMVtpXSA9IHMxW1NBMVtpXV07IC8vIGdldCBpbmRleCBpbiBzCiAgICBmb3IgKGkgPSBuMTsgaSA8IG47IGkrKykKICAgICAgICBTQVtpXSA9IC0xOyAvLyBpbml0IFNBW24xLi5uLTFdCiAgICBmb3IgKGkgPSBuMSAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgaiA9IFNBW2ldOwogICAgICAgIFNBW2ldID0gLTE7CiAgICAgICAgU0FbLS1ia3RbY2hyKGopXV0gPSBqOwogICAgfQogICAgaW5kdWNlU0FsKHQsIFNBLCBzLCBia3QsIG4sIEssIGNzLCBmYWxzZSk7CiAgICBpbmR1Y2VTQXModCwgU0EsIHMsIGJrdCwgbiwgSywgY3MsIHRydWUpOwogICAgZnJlZShia3QpOwogICAgZnJlZSh0KTsKfQoKY29uc3QgaW50IG1heG4gPSAyMDAwMDA7CmludCBzYVttYXhuXTsKaW50IGxjcFttYXhuXTsKaW50IF9yYW5rW21heG5dOwp1bnNpZ25lZCBjaGFyICpzOwppbnQgbjsKCnZvaWQgY2FsY19sY3AoKSB7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykKICAgICAgICBfcmFua1tzYVtpXV0gPSBpOwogICAgZm9yIChpbnQgaSA9IDAsIGggPSAwOyBpIDwgbjsgaSsrKSB7CiAgICAgICAgaWYgKF9yYW5rW2ldIDwgbiAtIDEpIHsKICAgICAgICAgICAgZm9yIChpbnQgaiA9IHNhW19yYW5rW2ldICsgMV07IHNbaSArIGhdID09IHNbaiArIGhdOyArK2gpCiAgICAgICAgICAgICAgICA7CiAgICAgICAgICAgIGxjcFtfcmFua1tpXV0gPSBoOwogICAgICAgICAgICBpZiAoaCA+IDApCiAgICAgICAgICAgICAgICAtLWg7CiAgICAgICAgfQogICAgfQp9CgppbnQgbWFpbigpIHsKICAgIHN0cmluZyBzdHIgPSAiQ0NDQ0MiOwogICAgbiA9IHN0ci5zaXplKCk7CiAgICBzID0gKHVuc2lnbmVkIGNoYXIqKSBzdHIuY19zdHIoKTsKICAgIFNBX0lTKHMsIHNhLCBuICsgMSwgMjU2LCAxKTsKICAgIGNhbGNfbGNwKCk7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICBjb3V0IDw8IHN0ci5zdWJzdHIoc2FbaSArIDFdKTsKICAgICAgICBpZiAoaSA8IG4gLSAxKQogICAgICAgICAgICBjb3V0IDw8ICIgIiA8PCBsY3BbaSArIDFdOwogICAgICAgIGNvdXQgPDwgZW5kbDsKICAgIH0KfQ==