首页 > 代码库 > [luoguP2870] [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold(后缀数组)

[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(\n);48     }49     return 0;50 }
View Code

 

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