zoukankan      html  css  js  c++  java
  • POJ3261 Milk Patterns 【后缀数组】

    牛奶模式
    时间限制: 5000MS   内存限制: 65536K
    提交总数: 16796   接受: 7422
    案件时间限制: 2000MS

    描述

    农夫约翰已经注意到,他的牛奶的质量每天都在变化。经进一步调查,他发现虽然不能预测一天到下一天的牛奶质量,但每天的牛奶质量有一些规律。

    要执行严格的研究,他已经发明了其中每个奶样本被记录为0到1,000,000之间的整数一个复杂的分类方案,并且已经从单一的母牛超过记录数据Ñ(1≤ Ñ ≤20000)天。他希望找到其等同至少K(2≤重复样品的最长图案ķ ≤ Ñ)次。这可能包括重叠模式 - 例如,1 2 3 2 3 2 3 1重复2 3 2 3。

    通过找到样本序列中最长的重复子序列来帮助Farmer John。保证至少有一个子序列重复至少K次。

    输入

    第1行:两个空格分隔的整数:NK 
    第2行N + 1:N个整数,每行一个,第i天的牛奶质量出现在第i行。

    产量

    第1行:一个整数,至少出现K的最长模式的长度

    示例输入

    8 2
    1
    2
    3
    2
    3
    2
    3
    1

    示例输出

    4


    开心,1A后缀数组【后缀数组还很渣。。】,虽然是一道板题 + 水题

    题目所求就是出现K次的最长子串

    我们求出height后二分答案

    对于二分出来的长度len,我们尝试在height数组中连续找出K个height[i] >= len,如果找得到,说明存在长度为len的子串重复了至少K次

    最后就是答案了【是不是很水> <】

    【题外:

    本蒟蒻现在要开始刷后缀数组!!谁也阻挡不了我> <

    搜索BZOJ后缀数组:P4310  P3230  P4698  P2946  P2251  P4556  P4270  P4516

    nice,开刷

    唔?4310去哪了

    3230怎么也找不到。。。。。。。。

    。。。。。。。。

    ~~没有权限的悲哀~~

    看来真的要节衣缩食买个权限狗了><

    先刷刷POJ吧。。。。

    哦代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
    using namespace std;
    const int maxn = 20005,maxm = 1000005,INF = 1000000000;
    inline int RD(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
    	return out * flag;
    }
    int n,K,A[maxn],sa[maxn],rank[maxn],height[maxn],t1[maxn],t2[maxn],m = 0,c[maxm];
    void SA(){
    	int *x = t1,*y = t2;
    	for (int i = 0; i <= m; i++) c[i] = 0;
    	for (int i = 1; i <= n; i++) c[x[i] = A[i]]++;
    	for (int i = 1; i <= m; i++) c[i] += c[i - 1];
    	for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
    	for (int k = 1; k <= n; k++){
    		int p = 0;
    		for (int i = n - k + 1; i <= n; i++) y[++p] = i;
    		for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
    		for (int i = 0; i <= m; i++) c[i] = 0;
    		for (int i = 1; i <= n; i++) c[x[y[i]]]++;
    		for (int i = 1; i <= m; i++) c[i] += c[i - 1];
    		for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i];
    		swap(x,y);
    		p = 1; x[sa[1]] = 1;
    		for (int i = 2; i <= n; i++)
    			x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
    		if (p >= n) break;
    		m = p;
    	}
    	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
    	int k = 0;
    	for (int i = 2; i <= n; i++){
    		if (k) k--;
    		int j = sa[rank[i] - 1];
    		while (A[i + k] == A[j + k]) k++;
    		height[rank[i]] = k;
    	}
    }
    bool check(int len){
    	int cnt = 1;
    	for (int i = 2; i <= n; i++)
    		if (height[i] >= len) {cnt++;if (cnt >= K) return true;}
    		else cnt = 1;
    	return false;
    }
    int main(){
    	n = RD(); K = RD();
    	REP(i,n) m = max(m,A[i] = RD());
    	SA();
    	int l = 1,r = n,mid;
    	while (l < r){
    		mid = l + r + 1 >> 1;
    		if (check(mid)) l = mid;
    		else r = mid - 1;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    


  • 相关阅读:
    设计改进ls代码实现更多功能
    20181328 《网络攻防》 EXP5 信息收集与漏洞扫描
    Socket 实验代码
    冲刺第一天——安装熟悉所使用的软件及其环境配置
    20181328 《网络对抗技术》Exp3 免杀原理与实践
    20181328 网络攻防实验一 PC平台逆向破解
    20181328 网络攻防实验一 PC平台逆向破解(最终版)
    20181328祝维卿——Exp2后门原理与实践
    设计实现ls功能
    Sql 2008 : 数据库分文件组(指定磁盘), 映射分区表使用不同的文件组详解(阻止保存要求重新创建表的更改?)
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282772.html
Copyright © 2011-2022 走看看