[luoguP2870] [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold(后缀数组)

传送门

数据小的话贪心就行。

可以把这个串翻转再接到后面,再求后缀数组,求出 rank 数组就很简单了。

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 60001
 4 
 5 int n, len, m = 256, sum;
 6 int buc[N], x[N], y[N], sa[N], rank[N];
 7 char s[N];
 8 
 9 inline void build_sa()
10 {
11     int i, k, p;
12     for(i = 0; i < m; i++) buc[i] = 0;
13     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
14     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
15     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
16     for(k = 1; k <= len; k <<= 1)
17     {
18         p = 0;
19         for(i = len - 1; i >= len - k; i--) y[p++] = i;
20         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
21         for(i = 0; i < m; i++) buc[i] = 0;
22         for(i = 0; i < len; i++) buc[x[y[i]]]++;
23         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
24         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
25         std::swap(x, y);
26         p = 1, x[sa[0]] = 0;
27         for(i = 1; i < len; i++)
28             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
29         if(p >= len) break;
30         m = p;
31     }
32 }
33 
34 int main()
35 {
36     int i, l, r;
37     scanf("%d", &n);
38     len = n * 2;
39     for(i = 0; i < n; i++) getchar(), s[i] = getchar(), s[len - i - 1] = s[i];
40     build_sa();
41     for(i = 0; i < len; i++) rank[sa[i]] = i;
42     l = 0, r = n - 1;
43     while(l <= r)
44     {
45         if(rank[l] <= rank[len - r - 1]) putchar(s[l++]);
46         else putchar(s[r--]);
47         if(++sum == 80) sum = 0, putchar('
');
48     }
49     return 0;
50 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/6984247.html