博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 3581 Sequence(后缀数组)题解
阅读量:5142 次
发布时间:2019-06-13

本文共 2821 字,大约阅读时间需要 9 分钟。

题意:

已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么?

思路:

因为\(str_1 > max\{str_2,str_3 \cdots str_n\}\),所以第一部分直接翻转后跑\(sa\)求字典序最小就行了。那么现在问题转化为:把这个字符串分成两半,然后每组都翻转,问字典序最小是什么?

我们假设这个字符串为\(s_1s_2 \cdots s_n\),那么可以得到分成两半反转后为\(s_ks_{k-1}s_{k-2} \cdots s_1s_ns_{n-1} \cdots s_{k+1}\),我们可以发现,这个串其实就是\(s_ns_{n-1}s_{n-2} \cdots s_1s_ns_{n-1} \cdots s_{1}\)的一个子串,那么我就把这个串反向复制两遍,然后后缀数组求字典序最小即可。
tips:多组输入必wa

代码:

#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 4e5 + 10;const int INF = 0x3f3f3f3f;const ull seed = 11;const int MOD = 1e9 + 7;using namespace std;int str[maxn];int t1[maxn], t2[maxn], c[maxn];int sa[maxn];int rk[maxn];int height[maxn];bool cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l];}void da(int *str, int n, int m){ n++; int i, j, p, *x = t1, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i] = str[i]]++; for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i; for(j = 1; j <= n; j <<= 1){ p = 0; for(i = n - j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 1; i < m; i++) c[i] += c[i - 1]; for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++; if(p >= n) break; m = p; }// int k = 0;// n--;// for(i = 0; i <= n; i++) rk[sa[i]] = i;// for(i = 0; i < n; i++){// if(k) k--;// j = sa[rk[i] - 1];// while(str[i + k] == str[j + k]) k++;// height[rk[i]] = k;// }}vector
vv;int s[maxn];int ans[maxn];int main(){ int n; int Max; scanf("%d", &n); vv.clear(); for(int i = 1; i <= n; i++) scanf("%d", &s[i]), vv.push_back(s[i]); sort(vv.begin(), vv.end()); vv.erase(unique(vv.begin(), vv.end()), vv.end()); for(int i = 1; i <= n; i++){ s[i] = lower_bound(vv.begin(), vv.end(), s[i]) - vv.begin() + 1; } Max = vv.size() + 2; //1 int len = n - 2; int cnt = 0; for(int i = len, j = 0; i >= 1; i--, j++){ str[j] = s[i]; } str[len] = 0; da(str, len, Max); for(int i = sa[1]; i < len; i++){ ans[cnt++] = str[i]; } //2 len = 0; for(int i = n; i > cnt; i--){ str[len++] = s[i]; } for(int i = n; i > cnt; i--){ str[len++] = s[i]; } str[len] = 0; da(str, len, Max); int st; for(int i = 1; ; i++){ if(sa[i] < len / 2 && sa[i] != 0){ st = sa[i]; break; } } for(int i = st; cnt < n; i++){ ans[cnt++] = str[i]; } for(int i = 0; i < cnt; i++){ printf("%d\n", vv[ans[i] - 1]); } return 0;}

转载于:https://www.cnblogs.com/KirinSB/p/11281267.html

你可能感兴趣的文章
Eclipse Python插件 PyDev
查看>>
selenium+python3模拟键盘实现粘贴、复制
查看>>
网站搭建(一)
查看>>
Spring JDBCTemplate
查看>>
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
面试时被问到的问题
查看>>
当前记录已被另一个用户锁定
查看>>
Node.js 连接 MySQL
查看>>
那些年,那些书
查看>>
注解小结
查看>>
java代码编译与C/C++代码编译的区别
查看>>
Bitmap 算法
查看>>
转载 C#文件中GetCommandLineArgs()
查看>>
list control控件的一些操作
查看>>
绝望的第四周作业
查看>>