题意:n个数字组成的序列,第一个数字最大,,把序列分成3部分,每个部分分别翻转,输出翻转后字典序最小的序列。。
后缀数组变一下,,先求出 第一个分割的位置,,然后再求一次后缀数组,,求出第二个位置。。输出就好了。
此题要采用单组输入。。。
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef unsigned long long ull; 16 typedef long long ll; 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-8; 19 const int maxn = 2e5+10; 20 int s[maxn], rev_s[maxn << 1]; 21 int sa[maxn], rank[maxn], tmp[maxn]; 22 int k, sort_len; 23 bool cmp(int i, int j) 24 { 25 if (rank[i] != rank[j]) 26 return rank[i] < rank[j]; 27 else 28 { 29 int x = i + k <= sort_len ? rank[i+k] : -1; 30 int y = j + k <= sort_len ? rank[j+k] : -1; 31 return x < y; 32 } 33 } 34 void build_sa(int str[], int len) 35 { 36 sort_len = len; 37 for (int i = 0; i <= len; i++) 38 { 39 sa[i] = i; 40 rank[i] = i < len ? str[i] : -1; 41 } 42 for (k = 1; k <= len; k *= 2) 43 { 44 sort(sa, sa + len + 1, cmp); 45 tmp[sa[0]] = 0; 46 for (int i = 1; i <= len; i++) 47 { 48 tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1],sa[i]) ? 1 : 0); 49 } 50 for (int i = 0; i <= len; i++) 51 rank[i] = tmp[i]; 52 } 53 } 54 int main(void) 55 { 56 #ifndef ONLINE_JUDGE 57 freopen("in.txt","r",stdin); 58 #endif 59 int n; 60 //while (~scanf ("%d", &n)) 61 scanf ("%d", &n); 62 { 63 for (int i = 0; i < n; i++) 64 scanf ("%d", s + i); 65 reverse_copy(s, s + n, rev_s); 66 build_sa(rev_s, n); 67 int pos1; 68 for (int i = 0; i <= n; i++) 69 { 70 pos1 = n - sa[i] - 1; 71 if (pos1 >= 0 && pos1 <= n - 3) 72 break; 73 } 74 int len = n - pos1 - 1; 75 reverse_copy(s+pos1+1, s+n, rev_s); 76 reverse_copy(s+pos1+1, s+n, rev_s+len); 77 build_sa(rev_s, len << 1); 78 int pos2; 79 for (int i = 0; i <= 2 * len; i++) 80 { 81 pos2 = len - sa[i] - 1; 82 if (sa[i] < len && pos1+1+pos2 < n-1) 83 break; 84 } 85 for (int i = pos1; i >= 0; i--) 86 printf("%d\n",s[i]); 87 for (int i = pos2+pos1+1; i > pos1; i--) 88 printf("%d\n",s[i]); 89 for (int i = n-1; i > pos2+pos1+1; i--) 90 printf("%d\n", s[i]); 91 } 92 return 0; 93 }
时间: 2024-10-12 05:59:43