• BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)


    直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门

    但是本蒟蒻不会后缀数组
    Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2007 Dec]队列变换

    于是就hash后二分找相同的最长区间,然后比较后一个谁更小…

    时间复杂度O(nlogn)O(nlogn).

    注意先在最后加一个极大值.因为如果一个序列A到末尾刚好与序列B的一段相等,那么一定是取B更优,因为B后面可能有更小的.

    hack数据

    4 2 2 2 1
    3 2 2 2

    如果没有加极大值,OJ上能A,但是这组数据会WA掉.

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    char cb[1<<15],*cs=cb,*ct=cb;
    #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
    template<class T>inline void read(T &res) {
    	char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
    	for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
    }
    const int MAXN = 200005 ;
    const int p = 137;
    int n, m, a[MAXN], b[MAXN], A[MAXN], B[MAXN], mul[MAXN];
    inline int hsh(int *H, int l, int r) {
        return l <= r ? H[r] - H[l-1] * mul[r-l+1] : 0;
    }
    inline int lcp(int i, int j) {
        int l = 0, r = min(n-i+1, m-j+1), mid;
        while(l < r) {
            mid = (l + r + 1) >> 1;
            if(hsh(A, i, i+mid-1) == hsh(B, j, j+mid-1)) l = mid;
            else r = mid-1;
        }
        return l;
    }
    int main() {
    	int i, j, k;
    	read(n); for(i = 1; i <= n; ++i) read(a[i]), A[i] = A[i-1] * p + a[i]; a[n+1] = 1005;
        read(m); for(i = 1; i <= m; ++i) read(b[i]), B[i] = B[i-1] * p + b[i]; b[m+1] = 1005;
        for(mul[0] = 1, i = 1; i <= n || i <= m; ++i) mul[i] = mul[i-1] * p;
        for(i = j = 1; i <= n && j <= m; printf("%d ", a[i+k] < b[j+k] ? a[i++] : b[j++])) k = lcp(i, j);
        while(i <= n) printf("%d ", a[i++]);
        while(j <= m) printf("%d ", b[j++]);
    }
    
    
  • 相关阅读:
    python学习笔记之生成器和迭代器、内置函数
    python学习笔记之装饰器(语法糖)
    python学习笔记第三天
    python学习笔记第二天
    Python学习笔记第一天
    获取系统所有软件的卸载信息
    读取注册表获取计算机上已安装程序的信息
    关机重启后运行父进程
    系统关机重启,提升进程权限
    修改用户密码
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039325.html
Copyright © 2020-2023  润新知