Problem - 2148F - Codeforces[字符串后缀排序]
Problem - 2148F - Codeforces题意很简单 我们可以随意防止字符串 按照从上到下 如果最后一层某个位置没有字符串 那么上面的字符串就会掉下来到最后一层 求字典序最小的最下层的字符串首先 最朴素的思想 我们会找出当前最小长度的字符串 长度k 然后截取所有字符串的前k个前缀元素 然后排序 找到最小的一个 将整个字符串填进去 然后从k到下一个长度如此反复 但是排序和遍历过多 时间复杂度过大 这是从从左到右遍历比较后缀数字的大小这个时候 我们可以用类似于后缀数组的倍增思想进行排序我们从后往前遍历 用数组res 存储所有长度大于当前长度len的数组的索引然后维护一个rk数组 表示数组的排名(按照字典序)我们从后往前遍历 对于最后一位 直接按照最后一位的所有数组当前位置的字符进行排序往前遍历的时候 我们可以维护一个vectorarreyint,3 分别存储 {当前位置的字符 当前位置的后缀 在上一次遍历的排名 以及数组索引 }排序完成后 第一名的就是当前位置的最优索引 然后更新一下排名 便于往前遍历的时候复用然后进行排序 这样可以复用后缀大小的关系 直接解决包含当前位的后缀的大小的问题最后生成答案的时候 按照每个分界位置的最优选择进行生成即可代码如下#include bits/stdc.h using namespace std; void solve(){ int n; cinn; vectorvectorintres; vectorvectorinta(n1); int maxlen0; for(int i1;in;i){ int k; cink; maxlenmax(maxlen,k); a[i].assign(k1,0); for(int j1;jk;j){ cina[i][j]; while(res.size()j)res.push_back({}); res[j].push_back(i); } } vectorintrk(n1,-1); vectorintminidx(maxlen1,0); for(int imaxlen;i1;i--){ vectorarrayint,3cur; for(auto j:res[i]){ cur.push_back({a[j][i],rk[j],j}); } sort(cur.begin(),cur.end()); minidx[i]cur[0][2]; int rkk0; for(auto j:cur){ rk[j[2]]rkk; } } vectorintans; while(ans.size()maxlen){ int tmpans.size(); auto v a[minidx[tmp1]]; for(int itmp1;iv.size();i){ ans.push_back(v[i]); } } for(auto x:ans)coutx ; cout\n; } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t; cint; while(t--)solve(); return 0; }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2480282.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!