对于height的维护还是不太理解。
后缀数组裸题:
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 80000
int s[maxn];
int sa[maxn];
int n, m;
int t[maxn], t2[maxn], c[maxn];
int Rank[maxn],height[maxn];
void build_sa(int n,int m)
{
int i,*x=t, *y=t2;
for (i=0; i<m; i++) c[i]=0;
for (i=0; i<n; i++) c[x[i]=s[i]]++;
for (i=1; i<m; i++) c[i]+=c[i-1];
for (i=n-1; i>=0; i--) sa[--c[x[i]]]=i;
for (int k=1;k<=n;k<<=1) {
int p=0;
for (i=n-k;i<n;i++) y[p++]= i;
for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=0;i<m;i++) c[i]=0;
for (i=0;i<n;i++) c[x[y[i]]]++;
for (i=0;i<m;i++) c[i] += c[i-1];
for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for (i=1;i<n;i++)
x[sa[i]]= y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p-1:p++;
if (p>=n) break;
m=p;
}
}
void getheight()
{
int k = 0;
for (int i=0;i<=n;i++) Rank[sa[i]]=i;
for (int i=0;i<n;i++) {
if (k) k--;
int j=sa[Rank[i]-1];
while (s[i+k]==s[j+k]) k++;
height[Rank[i]]=k;
}
}
bool valid(int ans,bool flag)
{
int cnt=0 ,pre=0, suf=0 ;
for (int i=1; i<=n; i++) {
if (height[i]>=ans) {
if (!cnt) {
cnt=1;
pre=max(pre,sa[i-1]);
}
cnt++;
pre=max(sa[i],pre);
}
else {
if (cnt>=m)
if (!flag) return true;
else suf=max(pre,suf);
cnt = pre = 0;
}
}
if (cnt>=m)
if (!flag) return true;
else suf=max(pre,suf);
if(!flag) return false;
else printf("%d %d\n",ans,suf);
return 0;
}
int main()
{
freopen("1.in","r",stdin);
char str[maxn];
while (scanf("%d",&m)!=EOF && m) {
scanf("%s",str);
if (m==1) {
printf("%d 0\n",strlen(str));
continue;
}
for (n=0;str[n];n++)
s[n]=str[n]-'a'+1;
s[n]=0;
build_sa(n+1,27);
getheight();
if (!valid(1,false)) {
printf("none\n");
continue;
}
int p=0, q=n+1, mid, ans=1;
while (p<=q) {
mid = (p+q)>>1;
if (valid(mid,false)) {
ans = mid;
p = mid+1;
}
else q = mid-1;
}
valid(ans,true);
}
return 0;
}
字符串hash:
hash[i]=s[i]+s[i+1]*x+...+s[n-1]*x^n-1-i;
hash[i]=hash[i+1]*x+s[i];
hash[i,L]=hash[i]-hash[i+L]*x^L;
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 40005
#define x 123
int n, m, pos ;
unsigned long long h[maxn], xp[maxn];
unsigned long long hash[maxn];
int rank[maxn];
int cmp(const int &a,const int &b)
{
return hash[a]<hash[b] || (hash[a]==hash[b] && a<b);
//frome latge to small
}
int possible (int L) {
int c=0;
pos=-1;
for (int i=0;i<n-L+1;i++) {
rank[i]=i;
hash[i]=h[i]-h[i+L]*xp[L];
}
sort(rank,rank+n-L+1,cmp);
for (int i=0;i<n-L+1;i++) {
if (i==0 || hash[rank[i]]!=hash[rank[i-1]]) c=0;
if (++c >= m) pos=max(pos,rank[i]);
}
return pos>=0;
}
int main()
{
freopen("1.in","r",stdin);
char s[maxn];
while (scanf("%d",&m)==1 && m) {
scanf("%s",s);
n = strlen(s);
h[n]=0;
for (int i=n-1;i>=0;i--) h[i] = h[i+1]*x+s[i]-'a';
xp[0]=1;
for (int i=1;i<=n;i++) xp[i] = xp[i-1]*x;
if (!possible(1)) printf("none\n");
else {
int L=1, R = n+1;
while (R-L>1) {
int M = L + (R-L)/2;
if (possible(M)) L = M;
else R = M;
}
possible(L);
printf("%d %d\n",L,pos);
}
}
return 0;
}