P2852 [USACO06DEC]Milk Patterns G
題目描述
Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can’t predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.
To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns – 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.
Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.
農夫John發現他的奶牛產奶的質量一直在變動。經過細致的調查,他發現:雖然他不能預見明天產奶的質量,但連續的若干天的質量有很多重疊。我們稱之為一個“模式”。 John的牛奶按質量可以被賦予一個0到1000000之間的數。并且John記錄了N(1<=N<=20000)天的牛奶質量值。他想知道最長的出現了至少K(2<=K<=N)次的模式的長度。比如1 2 3 2 3 2 3 1 中 2 3 2 3出現了兩次。當K=2時,這個長度為4。
輸入格式
Line 1: Two space-separated integers: N and K
Lines 2…N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.
輸出格式
Line 1: One integer, the length of the longest pattern which occurs at least K times
輸入輸出樣例
輸入 #1復制
輸出 #1復制
4題解:
題目自帶翻譯,愛了愛了
題意很明確了,其實就是求出現至少k次的子串的最大長度
這是后綴數組Height的應用
后綴數組這里就不介紹了講解鏈接
子串可以看做是后綴的前綴(想盡辦法和后綴扯上關系),出現k次的子串說明至少有k個后綴的lcp是這個子串,我們對后綴排序,說明至少有連續k個后綴的LCP是這個后綴,既然是連續,那么我們只需要看頭和尾就行
所以,求出每相鄰k-1個height的最小值,然后求這些最小值的最大值就是我們要的答案,注意,k一開始要減1,因為height[i]是當前第i個串和第i-1個串,涉及兩個串,所以k一開始要減1
可以用單調隊列O(n)解決
這也算是后綴數組Height應用的模板題,這幾天做了不少后綴數組的題,題目的難度評分都很高,基本上都是這種
但實際大部分都是套上模板就能做的,因為本身這個算法就比較難,所以背過模板會遷移就能結果后綴數組的大部分問題
代碼:
oi wiki的模板
// Problem: P2852 [USACO06DEC]Milk Patterns G // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P2852 // Memory Limit: 125 MB // Time Limit: 1000 ms // Data:2021-08-22 14:25:39 // By Jozky#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef LOCALstartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef LOCALendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int MAXN= 1000005;char ch[MAXN], all[MAXN]; int sa[MAXN], rk[MAXN], height[MAXN], tax[MAXN], tp[MAXN], a[MAXN], n, m; char str[MAXN]; //rk[i] 第i個后綴的排名; sa[i] 排名為i的后綴位置; height[i] 排名為i的后綴與排名為(i-1)的后綴的LCP //tax[i] 計數排序輔助數組; tp[i] rk的輔助數組(計數排序中的第二關鍵字),與sa意義一樣。 //a為原串 void RSort() {//rk第一關鍵字,tp第二關鍵字。for (int i= 0; i <= m; i++)tax[i]= 0;for (int i= 1; i <= n; i++)tax[rk[tp[i]]]++;for (int i= 1; i <= m; i++)tax[i]+= tax[i - 1];for (int i= n; i >= 1; i--)sa[tax[rk[tp[i]]]--]= tp[i]; //確保滿足第一關鍵字的同時,再滿足第二關鍵字的要求 } //計數排序,把新的二元組排序。int cmp(int* f, int x, int y, int w) {return f[x] == f[y] && f[x + w] == f[y + w]; } //通過二元組兩個下標的比較,確定兩個子串是否相同 int maxx; void Suffix() {//safor (int i= 1; i <= n; i++)rk[i]= a[i], tp[i]= i;m= maxx, RSort(); //一開始是以單個字符為單位,所以(m = 127)for (int w= 1, p= 1, i; p < n; w+= w, m= p) { //把子串長度翻倍,更新rk//w 當前一個子串的長度; m 當前離散后的排名種類數//當前的tp(第二關鍵字)可直接由上一次的sa的得到for (p= 0, i= n - w + 1; i <= n; i++)tp[++p]= i; //長度越界,第二關鍵字為0for (i= 1; i <= n; i++)if (sa[i] > w)tp[++p]= sa[i] - w;//更新sa值,并用tp暫時存下上一輪的rk(用于cmp比較)RSort(), swap(rk, tp), rk[sa[1]]= p= 1;//用已經完成的sa來更新與它互逆的rk,并離散rkfor (i= 2; i <= n; i++)rk[sa[i]]= cmp(tp, sa[i], sa[i - 1], w) ? p : ++p;}//離散:把相等的字符串的rk設為相同。//LCPint j, k= 0;for (int i= 1; i <= n; height[rk[i++]]= k)for (k= k ? k - 1 : k, j= sa[rk[i] - 1]; a[i + k] == a[j + k]; ++k);//這個知道原理后就比較好理解程序 } int k; void Init() {read(n, k);// for (int i= 1; i <= n; i++)// printf("%c", str[i]);for (int i= 1; i <= n; i++)cin >> a[i], maxx= max(maxx, a[i]); } int main() {//rd_test();Init();Suffix();int ans= 0;deque<int> q;k--;// for (int i= 1; i <= n; i++)// cout << "hegiht[i]=" << height[i] << endl;for (int i= 1; i <= n; i++) {while (!q.empty() && q.front() + k <= i)q.pop_front();while (!q.empty() && height[q.back()] >= height[i])q.pop_back();q.push_back(i);if (i >= k)ans= max(ans, height[q.front()]);}cout << ans;//Time_test(); }/* 12323231 */總結
以上是生活随笔為你收集整理的P2852 [USACO06DEC]Milk Patterns G的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑C盘清理垃圾和缓存的办法电脑清理c盘
- 下一篇: 2020牛客国庆集训派对day8