以POJ 1743为例。模板中的基数排序基于前向星。
具体证明过程详见 算法合集之《后缀数组——处理字符串的有力工具》,很不错的一篇论文。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <ctime>
#include <iomanip>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-6)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000007
using namespace std;
const int MAXN = 20510;
int s[MAXN];
int Rank[2*MAXN],sa[2*MAXN],tr[2*MAXN],high[MAXN];
struct N
{
int v,next;
}edge[2*MAXN];
int tail[MAXN],Top;
inline void Link(int u,int v)
{
edge[Top].v = v;
edge[Top].next = -1;
edge[tail[u]].next = Top;
tail[u] = Top++;
}
void Get_SA(int *s,int n)
{
memset(Rank,0,sizeof(Rank));
memset(sa,0,sizeof(sa));
int i,j,k,ans,site;
for(i = max(n,200);i >= 0; --i)
tail[i] = i,edge[i].next = -1;
Top = max(n,200)+1;
for(i = 1; i <= n; ++i)
Link(s[i],i);
ans = 1,site = 1;
for(i = 0; i <= 200; ++i)
{
for(j = edge[i].next; j != -1; j = edge[j].next)
sa[site++] = edge[j].v,Rank[edge[j].v] = ans;
if(edge[i].next != -1)
ans++;
tail[i] = i,edge[i].next = -1;
}
for(k = 1;k <= n; k <<= 1)
{
Top = n+1;
for(i = 1;i <= n; ++i)
Link(Rank[sa[i]+k],sa[i]);
site = 1;
for(i = 0;i <= n; ++i)
{
for(j = edge[i].next;j != -1; j = edge[j].next)
sa[site++] = edge[j].v;
tail[i] = i,edge[i].next = -1;
}
Top = n+1;
for(i = 1;i <= n; ++i)
Link(Rank[sa[i]],sa[i]);
site = 1;
for(i = 1;i <= n; ++i)
{
for(j = edge[i].next;j != -1; j = edge[j].next)
sa[site++] = edge[j].v;
tail[i] = i,edge[i].next = -1;
}
for(tr[sa[1]] = 1,i = 2,ans = 1;i <= n; ++i)
{
if(Rank[sa[i]] != Rank[sa[i-1]] || Rank[sa[i]+k] != Rank[sa[i-1]+k])
ans++;
tr[sa[i]] = ans;
}
for(i = 1;i <= n; ++i)
Rank[i] = tr[i];
if(ans >= n)
break;
}
for(i = 1,k = 1;i <= n; ++i)
{
if(k) k--;
if(Rank[i] == 1) {k = 0;high[1] = n-sa[1]+1;continue;}
j = sa[Rank[i]-1];
while(i+k <= n && j+k <= n && s[i+k] == s[j+k])
k++;
high[Rank[i]] = k;
}
//
// for(i = 1;i <= n; ++i)
// printf("i = %2d SA = %2d Rank = %2d high = %2d\n",i,sa[i],Rank[i],high[i]);
//以上为Rank,SA,HIGH的构造过程
}
bool Check(int mid,int n)
{
int L = sa[1],R = sa[1],i;
for(i = 2;i <= n; ++i)
{
if(high[i] >= mid)
{
L = min(sa[i],L),R = max(sa[i],R);
if(L+mid < R)
return true;
}
else
L = sa[i],R = sa[i];
}
return false;
}
int main()
{
int i,n;
while(scanf("%d",&n) && n)
{
for(i = 1;i <= n; ++i)
scanf("%d",&s[i]);
for(i = n;i >= 2; --i)
s[i] -= s[i-1]-100;
Get_SA(s,n);
int mid,anw = 0,Low = 1,High = n;
while(Low <= High)
{
mid = (Low + High)>>1;
if(Check(mid,n))
anw = max(anw,mid),Low = mid+1;
else
High = mid-1;
}
printf("%d\n",anw+1 < 5 ? 0 : anw+1);
}
return 0;
}