題意大概就是求一串數字中……應該說,當字符串看的數字中,找到一個至少出現k次的最長的子序列(可重複)
嗯。。課件完全看不懂在說什麼
“
”
???
首先我們考慮height數組的一個結論:Height[rank[i]]>=Height[rank[i-1]]-1
聯想其證明過程,顯然可以得到:若Height[i]!=0,則與Height[i-1]所得的值,必然是同一個前綴得到的
那麼我們可以得知:如果x個連續的Height值都大於T,那麼就有x+1個長度至少爲T的字符串
所以我們二分一個x,O(n)判斷即可
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <string>
#include <map>
#include <cstring>
#include <ctime>
#include <vector>
#define inf 1e9
#define ll long long
#define For(i,j,k) for(int i=j;i<=k;i++)
#define Dow(i,j,k) for(int i=k;i>=j;i--)
using namespace std;
inline void read(int &tx){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} tx=x*f; }
inline void write(ll x){ if (x<0) putchar('-'),x=-x; if (x>=10) write(x/10); putchar(x%10+'0'); }
inline void writeln(ll x){write(x);puts("");}
int s[50001];
int rk[50001],ys[50001],kk,n,het[50001];
struct node{int num,v,rk;} t[50001];
inline bool cmp(node x,node y){return x.rk!=y.rk?x.rk<y.rk:x.v<y.v;}
inline bool check(int x)
{
int tot=0,mx=0;
For(i,1,n)
{
if(het[i]>=x) tot++;else tot=0;
if(tot+1>=kk) return 1;
}
return 0;
}
int main()
{
read(n);read(kk);
For(i,1,n) read(s[i]);
For(i,1,n) rk[i]=s[i];
for(int i=0;(1<<i)<=n;i++)
{
For(j,1,n)
t[j].num=j,t[j].v=rk[j+(1<<i)],t[j].rk=rk[j];
sort(t+1,t+n+1,cmp);
int num=0;
For(j,1,n)
{
if(t[j].v!=t[j-1].v||t[j].rk!=t[j-1].rk) num++;
rk[t[j].num]=num;
}
}
For(i,1,n) ys[rk[i]]=i;
int k=0;
For(i,1,n)
{
for(k-=(k!=0);s[i+k]==s[ys[rk[i]-1]+k];k++);
het[rk[i]]=k;
}
int l=1,r=n,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) ans=max(ans,mid),l=mid+1;else r=mid-1;
}
writeln(ans);
}