• Luogu2852 [USACO06DEC]牛奶模式


    题目蓝链

    Description

    给定一个字符串,你需要找到一个最长在这个串中至少出现了(k)次的子串

    Solution

    我们首先对这个串进行后缀排序,那么对于排序后的任意一个区间([l, r]),那么原串中一定有(r - l + 1)个长度为(MIN_{i in (l, r]} {height_i})的相同字串

    于是我们就直接把(height)数列扫一边,同时维护一个单调队列,来维护任意相邻的(k - 1)(height)的最小值,答案便是这些最小值中的最大值

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define fst first
    #define snd second
    #define mp make_pair
    #define squ(x) ((LL)(x) * (x))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long LL;
    typedef pair<int, int> pii;
    
    template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
    template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
    
    inline int read() {
    	int sum = 0, fg = 1; char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
    	for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
    	return fg * sum;
    }
    
    const int maxn = 2e4 + 10;
    const int maxm = 1e6 + 10;
    
    int n, m, k;
    int S[maxn], sa[maxn], buc[maxm], rk[maxn], tmp[maxn], height[maxn];
    
    inline void Radix_sort() {
    	for (int i = 1; i <= m; i++) buc[i] = 0;
    	for (int i = 1; i <= n; i++) ++buc[rk[i]];
    	for (int i = 1; i <= m; i++) buc[i] += buc[i - 1];
    	for (int i = n; i >= 1; i--) sa[buc[rk[tmp[i]]]--] = tmp[i];
    }
    
    inline void get_sa() {
    	for (int i = 1; i <= n; i++) rk[i] = S[i] + 1, tmp[i] = i;
    	m = 1e6 + 1, Radix_sort();
    	for (int k = 1; k <= n; k <<= 1) {
    		int p = 0;
    		for (int i = n - k + 1; i <= n; i++) tmp[++p] = i;
    		for (int i = 1; i <= n; i++) if (sa[i] > k) tmp[++p] = sa[i] - k;
    		Radix_sort(), swap(rk, tmp);
    		rk[sa[1]] = 1, m = 1;
    		for (int i = 2; i <= n; i++)
    			rk[sa[i]] = (tmp[sa[i]] == tmp[sa[i - 1]] && tmp[sa[i] + k] == tmp[sa[i - 1] + k]) ? m : ++m;
    		if (m >= n) break;
    	}
    }
    
    inline void get_height() {
    	for (int i = 1, k = 0; i <= n; i++) {
    		if (k) --k;
    		int j = sa[rk[i] - 1];
    		while (S[i + k] == S[j + k]) ++k;
    		height[rk[i]] = k;
    	}
    }
    
    int main() {
    #ifdef xunzhen
    	freopen("milk.in", "r", stdin);
    	freopen("milk.out", "w", stdout);
    #endif
    
    	n = read(), k = read();
    	for (int i = 1; i <= n; i++) S[i] = read();
    	get_sa(), get_height();
    
    	deque<int> q;
    	int ans = 0;
    	for (int i = 2; i <= n; i++) {
    		while (!q.empty() && height[q.back()] > height[i]) q.pop_back();
    		q.push_back(i);
    		while (!q.empty() && q.front() <= i - k + 1) q.pop_front();
    		chkmax(ans, height[q.front()]);
    	}
    	cout << ans << endl;
    
    	return 0;
    }
    
  • 相关阅读:
    Centos7安装go.10.1环境
    centos7安装PHP5
    Linux 无文件攻击memfd_create()具体操作步骤
    centos7 '/mnt/hgfs'下共享文件夹不显示问题
    fiddler连接代理手机无法上网问题解决办法
    centos 镜像软件安装包版本低,手动安装过程
    0 upgraded, 0 newly installed, 0 to remove and 112 not upgraded解决方法
    JavaScript高级程序设计(第3版)第七章读书笔记
    JavaScript高级程序设计(第3版)第六章读书笔记
    JavaScript高级程序设计(第3版)第五章读书笔记
  • 原文地址:https://www.cnblogs.com/xunzhen/p/10614197.html
Copyright © 2020-2023  润新知