zoukankan      html  css  js  c++  java
  • BZOJ 4698: [SDOI2008]Sandy的卡片

    题面

    有权限号的去看吧
    Luogu

    Sol

    差分后就是求多个串的最长公共子串
    套路啊
    拼在一起用不同字符隔开,后缀数组,二分答案,分块height,开桶记录即可
    我把差分值离散了

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(2000000);
    
    IL ll Read(){
        RG char c = getchar(); RG ll x = 0, z = 1;
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int T, n, a[_], sa[_], rk[_], tmp[_], height[_], t[_], ans, mx, vis[_], cnt[1010], Index;
    int o[_], num[1010][1010], len, l[_];
     
    IL bool Cmp(RG int i, RG int j, RG int k){  return tmp[i] == tmp[j] && tmp[i + k] == tmp[j + k];  }
    
    IL void Suffix_Sort(){
        RG int m = mx;
        for(RG int i = 1; i <= n; ++i) ++t[rk[i] = a[i]];
        for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
        for(RG int i = n; i; --i) sa[t[rk[i]]--] = i;
        for(RG int k = 1; k <= n; k <<= 1){
            RG int l = 0;
            for(RG int i = n - k + 1; i <= n; ++i) tmp[++l] = i;
            for(RG int i = 1; i <= n; ++i) if(sa[i] > k) tmp[++l] = sa[i] - k;
            for(RG int i = 0; i <= m; ++i) t[i] = 0;
            for(RG int i = 1; i <= n; ++i) ++t[rk[tmp[i]]];
            for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
            for(RG int i = n; i; --i) sa[t[rk[tmp[i]]]--] = tmp[i];
            swap(rk, tmp); rk[sa[1]] = l = 1;
            for(RG int i = 2; i <= n; ++i) rk[sa[i]] = Cmp(sa[i - 1], sa[i], k) ? l : ++l;
            if(l >= n) break; m = l;
        }
        for(RG int i = 1, h = 0; i <= n; ++i){
    		if(h) --h;
            while(a[i + h] == a[sa[rk[i] - 1] + h]) ++h;
    		height[rk[i]] = h;
        }
    }
    
    IL bool Check(RG int x){
    	RG int tot = (vis[sa[1]] != 0); cnt[vis[sa[1]]] = ++Index;
    	for(RG int i = 2; i <= n; ++i){
    		if(height[i] >= x){
    			if(cnt[vis[sa[i]]] != Index) tot += (vis[sa[i]] != 0), cnt[vis[sa[i]]] = Index;
    		}
    		else cnt[vis[sa[i]]] = ++Index, tot = (vis[sa[i]] != 0);
    		if(tot == T) return 1;
    	}
    	return 0;
    }
    
    int main(RG int argc, RG char* argv[]){
    	T = Read();
    	for(RG int i = 1; i <= T; ++i){
    		l[i] = Read();
    		for(RG int j = 1; j <= l[i]; ++j) num[i][j] = Read();
    	}
    	for(RG int i = 1; i <= T; ++i)
    		for(RG int j = 1; j <= l[i]; ++j) o[++len] = num[i][j] = num[i][j + 1] - num[i][j];
    	sort(o + 1, o + len + 1); len = unique(o + 1, o + len + 1) - o - 1;
    	mx = len;
    	for(RG int i = 1; i <= T; ++i){
    		for(RG int j = 1; j <= l[i]; ++j){
    			num[i][j] = lower_bound(o + 1, o + len + 1, num[i][j]) - o;
    			a[++n] = num[i][j]; vis[n] = i;
    		}
    		a[++n] = ++mx;
    	}
    	Suffix_Sort();
    	Check(1);
    	RG int l = 0, r = n;
    	while(l <= r){
    		RG int mid = (l + r) >> 1;
    		if(Check(mid)) ans = mid + 1, l = mid + 1;
    		else r = mid - 1;
    	}
    	printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    How to build Linux system from kernel to UI layer
    Writing USB driver for Android
    Xposed Framework for Android 8.x Oreo is released (in beta)
    Linux Smartphone Operating Systems You Can Install Today
    Librem 5 Leads New Wave of Open Source Mobile Linux Contenders
    GUADEC: porting GNOME to Android
    Librem 5 – A Security and Privacy Focused Phone
    GNOME and KDE Join Librem 5 Linux Smartphone Party
    Purism计划推出安全开源的Linux Librem 5智能手机
    国产系统之殇:你知道的这些系统都是国外的
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8350093.html
Copyright © 2011-2022 走看看