s a sa sa 板子 ( s a 、 h e i g h t ) (sa、height) (sa、height)
s a sa sa 定义: s a [ i ] sa[i] sa[i] 记录排名为 i i i 的非空后缀的编号。
h e i g h t height height 定义: h e i g h t [ i ] height[i] height[i] 来记录排名为 i i i 的非空后缀与排名为 i − 1 i-1 i−1 的非空后缀的最长公共前缀的长度 ( 1 < = i < = n ) (1<=i<=n) (1<=i<=n), h e i g h t [ 1 ] = 0 height[1]=0 height[1]=0。
宏定义:
const int N = 1000010;
int n, m;
char s[N];
int sa[N], x[N], y[N], c[N], rk[N], height[N];
获得 s a : sa: sa:
void get_sa()
{
for (int i = 1; i <= n; i ++ ) c[x[i] = s[i]] ++ ;
for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];//前缀和
for (int i = n; i; i -- )sa[c[x[i]] -- ] = i;
for (int k = 1; k <= n; k <<= 1)
{
int num = 0;
for (int i = n - k + 1; i <= n; i ++ ) y[ ++ num] = i;
for (int i = 1; i <= n; i ++ )
if (sa[i] > k)
y[ ++ num] = sa[i] - k;
for (int i = 1; i <= m; i ++ ) c[i] = 0;
for (int i = 1; i <= n; i ++ ) c[x[i]] ++ ;
for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];
for (int i = n; i; i -- ) sa[c[x[y[i]]] -- ] = y[i], y[i] = 0;
swap(x, y);
x[sa[1]] = 1, num = 1;
for (int i = 2; i <= n; i ++ )
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++ num;
if (num == n) break;
m = num;
}
}
获得 h e i g h t : height: height:
void get_height()
{
for (int i = 1; i <= n; i ++ ) rk[sa[i]] = i;
for (int i = 1, k = 0; i <= n; i ++ )
{
if (rk[i] == 1) continue;
if (k) k -- ;
int j = sa[rk[i] - 1];
while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k ++ ;
height[rk[i]] = k;
}
}
m a i n : main: main:
int main()
{
scanf("%s", s + 1);
n = strlen(s + 1), m = 122;
get_sa();
get_height();
for (int i = 1; i <= n; i ++ ) printf("%d ", sa[i]);
puts("");
for (int i = 1; i <= n; i ++ ) printf("%d ", height[i]);
puts("");
return 0;
}