[Usaco2006 Dec] Milk Patterns 产奶的模式 - 后缀自动机
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Usaco2006 Dec] Milk Patterns 产奶的模式 - 后缀自动机相关的知识,希望对你有一定的参考价值。
Description
给定一个数字串 (S),求出现了 (k) 次的子串的最大长度。
Solution
考虑基于 std::map
的 SAM
出现 (k) 次的条件就是要求 (endpos) 集合的大小 (ge k)
于是我们在满足这个条件的所有节点的 (len) 中取最大即可
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
struct SAM {
int len[N], fa[N], ind, last;
map<int,int> ch[N];
int t[N], a[N], cnt[N], f[N];
SAM() { ind = last = 1; }
inline void extend(int id) {
int cur = (++ ind), p;
len[cur] = len[last] + 1;
cnt[cur] = 1;
for (p = last; p && !ch[p][id]; p = fa[p]) ch[p][id] = cur;
if (!p) fa[cur] = 1;
else {
int q = ch[p][id];
if (len[q] == len[p] + 1) fa[cur] = q;
else {
int tmp = (++ ind);
len[tmp] = len[p] + 1;
ch[tmp] = ch[q];
fa[tmp] = fa[q];
for (; p && ch[p][id] == q; p = fa[p]) ch[p][id] = tmp;
fa[cur] = fa[q] = tmp;
}
}
last = cur;
}
void calcEndpos() {
memset(t, 0, sizeof t);
for(int i=1; i<=ind; i++) t[len[i]]++;
for(int i=1; i<=ind; i++) t[i]+=t[i-1];
for(int i=1; i<=ind; i++) a[t[len[i]]--]=i;
for(int i=ind; i>=1; --i) cnt[fa[a[i]]]+=cnt[a[i]];
cnt[1] = 0;
}
int solve(int k)
{
int ans=0;
for(int i=1;i<=ind;i++)
{
if(cnt[i]>=k) ans=max(ans,len[i]);
}
return ans;
}
} sam;
int main() {
ios::sync_with_stdio(false);
int n,k,t;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>t;
sam.extend(t);
}
sam.calcEndpos();
cout<<sam.solve(k)<<endl;
}
以上是关于[Usaco2006 Dec] Milk Patterns 产奶的模式 - 后缀自动机的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式
BZOJ1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]
bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式