bzoj4104: [Thu Summer Camp 2015]解密运算
挖掘性质题,还是脑洞不够大只会40pt
首先可以发现,每个位置的字母都会放在给出的子串结尾有且仅有一次(废话)
然后据此就可以找出这个串是由哪些字母组成的了,排一波序就知道对于给出的子串的第一位置是啥了
既知道最后一个位置,又知道第一个位置,这两个位置是相邻的,确认两个字母的关系,假如互不相同就做完了
现在问题在于如何比较两个第一位置相同的子串谁在谁的前面
我的想法就此停滞。。。。。。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%分割线%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
我们可以发现,每个子串0以及它后面的一段是没有用的,对所有的子串排完序以后搞出来的顺序就是sa数组,我们不知道sa的具体值,但输入第i行给出的就是排名为i的后缀的前一个字母是什么,反过来说,我们可以知道某一个字母的后面是排名为i的后缀!这个产生了巨大的作用
接着是排序步骤,我们可以理解为把最后一个字母拉出来排序,首先第一关键字就是这个字母本身,第二关键字就是这个字母后面的后缀!
好妙啊
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const int _=1e2; const int maxn=2*1e5+_; pair<int,int>a[maxn]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) scanf("%d",&a[i].first),a[i].second=i; sort(a,a+n+1); int now=a[0].second; for(int i=1;i<n;i++) { printf("%d ",a[now].first); now=a[now].second; } printf("%d\n",a[now].first); return 0; }
pain and happy in the cruel world.