Sample Input
8 2
1
2
3
2
3
2
3
1
Sample Output
4
Source
USACO 2006 December Gold
题意:找出出现k次的可重叠的最长子串的长度
思路:其实通过做几道后缀数组,那么这道题就是模板水题了,通过二分长度,然后分成若干组去寻找答案
题意 问你出现大于等于k次的最长连续重叠子串长度
做法 和POJ1743做法一样 我们去二分这个长度 然后只需要height[i]>=mid的分为一组 组中字符串个数超过k即可
/*
if you can't see the repay
Why not just work step by step
rubbish is relaxed
to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod = (int)1e9+7;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
const int MAX_N = 3e4+5;
int wa[MAX_N],wb[MAX_N],wsf[MAX_N],wv[MAX_N],sa[MAX_N],n,b[MAX_N];
int Rank[MAX_N],height[MAX_N],s[MAX_N];
int str1[MAX_N],str2[MAX_N];
int cmp(int *r,int a,int b,int k)
{
return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0; i<m; i++) wsf[i]=0;
for(i=0; i<=n; i++) wsf[x[i]=r[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n; i>=0; i--) sa[--wsf[x[i]]]=i;
p=1;
j=1;
for(; p<=n; j*=2,m=p)
{
for(p=0,i=n+1-j; i<=n; i++) y[p++]=i;
for(i=0; i<=n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0; i<=n; i++) wv[i]=x[y[i]];
for(i=0; i<m; i++) wsf[i]=0;
for(i=0; i<=n; i++) wsf[wv[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
t=x;
x=y;
y=t;
x[sa[0]]=0;
for(p=1,i=1; i<=n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
}
}
void getheight(int *r,int n)//n为添加0后的总长
{
int i,j,k=0;
for(i=1; i<=n; i++) Rank[sa[i]]=i;
for(i=0; i<n; i++)
{
if(k)
k--;
else
k=0;
j=sa[Rank[i]-1];
while(r[i+k]==r[j+k])
k++;
height[Rank[i]]=k;
}
}
int main()
{
//ios::sync_with_stdio(false);
//freopen("a.txt","r",stdin);
//freopen("b.txt","w",stdout);
int t,k,n= 0;
scanf("%d%d",&t,&k);
for(int i = 1;i<=t;++i)
scanf("%d",&str1[i]),b[i] = str1[i];
sort(b+1,b+1+t);
int sz = unique(b+1,b+1+t)-b-1;
for(int i = 1;i<=t;++i)
s[n++] = (lower_bound(b+1,b+1+sz,str1[i])-b);
s[n] = 0;
int m = 20001;
getsa(s,sa,n,m);
getheight(s,n);
int l = 0,r = n+1;
while(l<=r)
{
int cnt = 1,mid = (l+r)>>1;
bool flag = false;
for(int i = 1;i<=n;++i)
{
if(height[i]>=mid) cnt++;
else
{
if(cnt>=k) flag = 1;
cnt = 1;
}
}
if(cnt>=k) flag = 1;
if(flag) l = mid + 1;
else r= mid - 1;
}
printf("%d\n",r);
//fclose(stdin);
//fclose(stdout);
//cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
return 0;
}