每日一题。。
这几天开始搞后缀数组,果然关键时候智商果然不够用,想到现在才有点眉目,虽然这种题千篇一律的模板,但是理解了才能运用的比较好,估计明天我就能自己写模板了。。
题意很明显,k个相同的子串,就是要在求height的时候多判断一下,过了。
#include<stdio.h>
#include<string.h>
#include<iostream>
#define rep(i,n) for(int i = 0;i < n; i++)
using namespace std;
const int size = 21000,INF = 1<<30,maxn=1000010;
char s[size];
int y;
int rk[maxn],sa[maxn],height[maxn],w[size],wa[maxn],res[maxn];
void getSa (int len,int up) {
int *k = rk,*id = height,*r = res, *cnt = wa;
rep(i,up) cnt[i] = 0;
rep(i,len) cnt[k[i] = w[i]]++;
rep(i,up) cnt[i+1] += cnt[i];
for(int i = len - 1; i >= 0; i--) {
sa[--cnt[k[i]]] = i;
}
int d = 1,p = 0;
while(p < len){
for(int i = len - d; i < len; i++) id[p++] = i;
rep(i,len) if(sa[i] >= d) id[p++] = sa[i] - d;
rep(i,len) r[i] = k[id[i]];
rep(i,up) cnt[i] = 0;
rep(i,len) cnt[r[i]]++;
rep(i,up) cnt[i+1] += cnt[i];
for(int i = len - 1; i >= 0; i--) {
sa[--cnt[r[i]]] = id[i];
}
swap(k,r);
p = 0;
k[sa[0]] = p++;
rep(i,len-1) {
if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d])
k[sa[i+1]] = p - 1;
else k[sa[i+1]] = p++;
}
if(p >= len) return ;
d *= 2,up = p, p = 0;
}
}
void getHeight(int len)
{
rep(i,len) rk[sa[i]] = i;
height[0] = 0;
int cn=1,flag=0,p=0,tmp;
for(int i = 0; i < len - 1; i++)
{
while(1)
{
flag=0;
if(i+p<len)
{
for(cn=1; cn<y; cn++)
{
// printf("?%d %d\n",w[i+p],w[tmp+p]);
if(rk[i]>=cn)
tmp=sa[rk[i]-cn];
else {flag=1 ;break;}
if(tmp+p<len)
{
if(w[i+p]!=w[tmp+p])
{
flag=1;
break;
}
}
else
{
flag=1;
break;
}
}
if(flag==1) break;
else p++;
}
else break;
}
// printf("%d",p);
height[rk[i]] = p;
p = max(0,p - 1);
//p=0;
}
}
int main()
{
int n,up=0;
scanf("%d%d",&n,&y);
for(int i=0; i<n; i++)
{
scanf("%d",&w[i]);
if(w[i]>up) up=w[i];
}
w[n++]=0;
getSa(n,up+1);
// for(int i=0;i<n;i++)
// printf(" %d ",sa[i]);
// printf("\n");
getHeight(n);
int ans=0;
for(int i=1; i<=n; i++)
{
ans=max(ans,height[i]);
}
printf("%d\n",ans);
return 0;
}