题目大意

给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T.\(len \leq 200000\)

题解

我们从归并排序的角度去想,每次把两者之一较小的取出来
遇到相等的元素的时候,排序时取那个都是一样的.
但是在这道题中我们是求字典序最小,这就不一样了.
我们不能任意取,这一步的决策其实是由后面的数字的大小决定的
怎么说呢...
方法蕴藏在这三张图里了,自己去悟吧。
黑色箭头表示选取,黑色圆圈表示确定选取序列的理由.
迭代第一次

迭代第二次

迭代第三次

剩下的略...
这个东西我们可以用后缀数组(lcp)来维护

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline void read(int &x){x=0;char ch;bool flag = false;while(ch=getchar(),ch<'!');if(ch=='-')ch=getchar(),flag = true;while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 410010;
int a[maxn],b[maxn],c[maxn];
int wa[maxn],wb[maxn],ws[maxn];
int sa[maxn],rank[maxn],height[maxn];
inline bool cmp(int *r,int i,int j,int l){return r[i] == r[j] && r[i+l] == r[j+l];
}
void da(int *r,int n,int m){int i,j,p,*x = wa,*y = wb;for(i=0;i<m;++i) ws[i] = 0;for(i=0;i<n;++i) ws[x[i] = r[i]]++;for(i=1;i<m;++i) ws[i] += ws[i-1];for(i=n-1;i>=0;--i) sa[--ws[x[i]]] = i;for(j=1,p=1;p<n;j<<=1,m=p){for(p=0,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) ws[i] = 0;for(i=0;i<n;++i) ws[x[y[i]]]++;for(i=1;i<m;++i) ws[i] += ws[i-1];for(i=n-1;i>=0;--i) sa[--ws[x[y[i]]]] = y[i];for(swap(x,y),p=1,i=1,x[sa[0]] = 0;i<n;++i)x[sa[i]] = cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;}
}
void get_h(int *r,int n){int i,j,k=0;for(i=1;i<=n;++i) rank[sa[i]] = i;for(i=0;i<n;height[rank[i++]] = k)for(k ? --k : 0,j = sa[rank[i]-1];r[i+k] == r[j+k];++k);
}
int loger[maxn],minn[maxn][22];
void pre(int *r,int n){loger[1] = 0;for(int i=2;i<=n;++i){loger[i] = loger[i-1];if( (1 << loger[i]+1 ) == i) ++loger[i];}for(int i=n;i>=1;--i){minn[i][0] = r[i];for(int j=1;(i + (1<<j) - 1) <= n;++j){minn[i][j] = min(minn[i][j-1],minn[i+(1<<j-1)][j-1]);}}
}
int lcp(int s,int t){s = rank[s];t = rank[t];if(s+1 > t) swap(s,t);++s;int k = loger[t-s+1];   return min(minn[s][k],minn[t-(1<<k)+1][k]);
}
int n,m,len;
inline bool order(int i,int j){int k = lcp(i,j);int x = (i+k) == n   ? 0x7f7f7f7f : c[i+k];int y = (j+k) == len ? 0x7f7f7f7f : c[j+k];return x <= y;
}
int q[maxn];
int main(){read(n);for(int i=0;i<n;++i){read(a[i]);c[i] = a[i];}c[n] = 1005;read(m);for(int i=0;i<m;++i){read(b[i]);c[n+i+1] = b[i];}len = n+m+1;c[len] = 0;da(c,len+1,1010);get_h(c,len);pre(height,len);int i=0,j=0,k=0;while(i < n && j < m){int x = order(i,j+n+1);if(x == 1) q[k++] = a[i++];else q[k++] = b[j++];}while(i < n) q[k++] = a[i++];while(j < m) q[k++] = b[j++];for(i=0;i<k;++i) printf("%d ",q[i]);getchar();getchar();return 0;
}

转载于:https://www.cnblogs.com/Skyminer/p/6407439.html

bzoj 4278 Tasowanie 后缀数组+贪心相关推荐

  1. BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组 + 贪心 + 细节

    Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串 ...

  2. BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组

    4278: [ONTAK2015]Tasowanie Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 426  Solved: 199 [Submit ...

  3. BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 居然把后缀数组写成n^2的..我真厉害.. 想了无数种方法,最后发现就是 ...

  4. bzoj 4278 [ONTAK2015]Tasowanie——后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4278 因为每次要放后缀较小的那个,所以把两个序列放在一起排序吧.改一改模板. 其实要改的地方 ...

  5. 后缀数组+贪心+隔板法

    题意:给你sa数组,就是每个排名的后缀开始下标,让你求有多少种满足要求的串,有那么一个原理,对于相邻排名的两个后缀,后缀i的首字母要不要大于i-1,的取决于,第二个字符的比较,如果i的第二个字符> ...

  6. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

  7. UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组、ST表)

    UOJ #219 BZOJ 4650 luogu P1117 [NOI2016]优秀的拆分 (后缀数组.ST表) 连NOI Day1T1都不会做...看了题解都写不出来还要抄Claris的代码.. 题 ...

  8. bzoj 1640 bzoj 1692: [Usaco2007 Dec]队列变换(后缀数组)

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1756  Solved: 737 [Submit][ ...

  9. 【BZOJ】1031: [JSOI2007]字符加密Cipher(后缀数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1031 很容易想到这就是将字符串复制到自己末尾然后后缀数组搞出sa然后按区间输出即可. 然后换了下模板 ...

最新文章

  1. 由于不知线程池的bug,某Java程序员叕被祭天
  2. 最新BERT相关论文汇总
  3. 浏览器窗口控制---使用localStorage
  4. 红黑联盟c语言教程,1.1.2 C语言的特点
  5. Rapidmind计算库性能测试
  6. javascript中对变量类型的推断
  7. 登录注册实现(服务器数据)
  8. Android中SimpleAdapter的使用—自定义列表
  9. (Android开发辅助工具)动态广播注册解注工具
  10. echarts词云图形状_词云图在自然语言中的应用,可以如此炫酷!
  11. java 内部类定于_搞懂 JAVA 内部类
  12. GridView position = 0重复加载的问题
  13. 项目中为什么用Docker?
  14. python贴吧签到-百度贴吧签到脚本
  15. RedHat免费订阅账号注册方式
  16. 低代码平台上的出入库管理
  17. 如何看待“英特尔是一家软件公司”?
  18. nRF 协议栈操作相关
  19. java 流计算_Java 流收集器 ( Stream Collectors ) ( 一 ) - 统计计算
  20. (装机)关于WINRE/ESP/LRS_ESP/MSR/PBR这些分区

热门文章

  1. 如何修改 SAP 登录界面的文字(事务码SE61)
  2. 历史精华文章分类汇总,祝大家中秋快乐!
  3. 视频语义显著实例分割数据集SESIV
  4. linux服务器开发板,linuxnfs服务器的建立,虚拟机、开发板间的通信
  5. Python进阶|聊聊异常处理
  6. 李沐分享斯坦福2021秋季新课:实用机器学习
  7. 计算机视觉论文-2021-06-16
  8. html与markdown互相转换
  9. 零基础入门深度学习 | 第二章:线性单元和梯度下降
  10. 在GIS中运用坐标系统