hdu3261

题意:

求至少出现k次的最长字符串(可重复)

题解:

后缀数组维护height数组只要找连续k个的最小值

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 1000010
int x[maxn],y[maxn],sa[maxn],height[maxn],
rank[maxn],c[maxn],a[maxn],h,t;
char s[maxn];
int n,m;
struct{
  int num,ans;
}b[maxn];
void asa(int n,int m)
{
  int p=0,f=0;
  for (int i=1;i<=m;i++) c[i]=0;
  for (int i=1;i<=n;i++) c[x[i]=a[i]]++;
  for (int i=1;i<=m;i++) c[i]+=c[i-1];
  for (int i=n;i;i--) sa[c[x[i]]--]=i;
  for(int i=1;i<=n&&p<=n;i<<=1)
  {
     p=0;
     for (int j=n-i+1;j<=n;j++) y[++p]=j;
     for (int j=1;j<=n;j++) 
       if (sa[j]>i) y[++p]=sa[j]-i;
     for (int j=1;j<=m;j++) c[j]=0;
     for (int j=1;j<=n;j++) c[x[y[j]]]++;
     for (int j=1;j<=m;j++) c[j]+=c[j-1];
     for (int j=n;j;j--) sa[c[x[y[j]]]--]=y[j];
     swap(x,y); x[sa[1]]=1; p=2;
     for (int j=2;j<=n;j++)
       x[sa[j]]=y[sa[j]]==y[sa[j-1]]&&y[sa[j]+i]==y[sa[j-1]+i]
       ?p-1:p++;
     m=p;
  } 
  for (int i=1;i<=n;i++) rank[sa[i]]=i;
  for (int i=1;i<=n;i++)
  {
    int j=sa[rank[i]-1];
    if (f) f--;
    while (a[i+f]==a[j+f]) f++;
    height[rank[i]]=f;
  }
}
void insert(int x,int y)
{
  while (t>=h&&b[t].ans>=x) t--;
  b[++t].num=y;
  b[t].ans=x;
}
int main()
{
  freopen("noip.in","r",stdin);
  freopen("noip.out","w",stdout);
  cin>>n>>m; m--;
  for (int i=1;i<=n;i++) cin>>a[i];
  asa(n,21000);
  for (int i=1;i<=m-1;i++) insert(height[i],i);
  int ans=0; h=1;
  for (int i=m;i<=n;i++)
  {
    insert(height[i],i);
    if (t>=h&&b[h].num<i-m+1) h++;
    ans=max(b[h].ans,ans);
  }
  cout<<ans;
  return 0;
}

 

posted @ 2018-02-20 13:29  尹吴潇  阅读(118)  评论(0编辑  收藏  举报