您的位置:首页 > 编程语言 > C语言/C++

Sa求法

2016-04-27 16:37 351 查看
#include <iostream>
#include <cstdio>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXN=20010;
int t1[MAXN],t2[MAXN],c[MAXN];

bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b] && r[a+l]== r[b+l];
}
void da(int str[],int sa[],int Rank[],int height[],int n,int m)
{
n++;
int i,j,p,*x =t1,*y=t2;
for (int i=0;i<m;i++)
c[i]=0;
for (int i=0;i<n;i++)
c[x[i]=str[i]]++;
for (int i=1;i<m;i++) c[i]+=c[i-1];
for (int i=n-1; i>=0; i--)
sa[--c[x[i]]] =i;
for (int j=1;j<=n;j <<=1)
{
p=0;
for (int i=n-j; i<n ; i++) y[p++] =i;
for (int i=0; i<n; i++)
if (sa[i]>=j) y[p++]=sa[i]-j;
for (int i=0; i<m; i++)
c[i]=0;
for (int i=0; i<n; i++)
c[x[y[i]]]++;
for (int i=1; i<m; i++)
c[i]+=c[i-1];
for (int i=n-1;i>=0;i--)
sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p=1; x[sa[0]] = 0;
for (int i=1; i<n ; i++ )
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
if (p>=n) break;
m=p;
}
int k=0;
n--;
for (int i=0;i<=n;i++)
Rank[sa[i]]=i;

for (int i=0;i<n;i++)
{
if (k) k--;
j=sa[Rank[i]-1];
while (str[i+k]==str[j+k]) k++;
height [Rank[i]] =k;
}

}

int Rank[MAXN],height[MAXN];
int RMQ[MAXN];
int mm[MAXN];
int best[20][MAXN];
void initRMQ(int n)
{
mm[0]=-1;
for (int i=1;i<=n;i++)
mm[i] = ((i&(i-1)) == 0) ? mm[i-1]+1:mm[i-1];
for (int i=1;i<=n;i++)
best[0][i]=i;
for (int i=1;i<=mm
;i++)
for (int j=1;j+(1<<i)-1<=n;j++)
{
int a=best[i-1][j];
int b=best[i-1][j+(1<<(i-1))];
if (RMQ[a]<RMQ[b]) best[i][j]=a;
else best[i][j]=b;
}
}

int askRMQ(int a,int b)
{
int t;
t=mm[b-a+1];
b-=(1<<t)-1;
a=best[t][a];
b=best[t][b];
return RMQ[a]<RMQ[b]?a:b;
}
int lcp(int a,int b)
{
a=Rank[a];
b=Rank[b];
if (a>b) swap(a,b);
return height[askRMQ(a+1,b)];
}
char str[MAXN];
int r[MAXN];
int sa[MAXN];

int main()
{
while (scanf("%s",str) ==1 )
{
int len=strlen(str);

int n=2*len+1;
for (int i=0;i<len;i++) r[i]=str[i];
for (int i=0;i<len;i++)
r[len+1+i] = str[len-1-i];
r[len] = 1;
r
= 0;

da(r,sa,Rank,height,n,250);

for (int i=1;i<=n;i++)
RMQ[i]=height[i];
initRMQ(n);

int ans=0,st;
int tmp;
for (int i=0;i<len;i++)
{
tmp=lcp(i,n-i);

if (2*tmp>ans)
{
ans=2*tmp;
st=i-tmp;
}
tmp=lcp(i,n-i-1);

if (2*tmp-1>ans)
{
ans=2*tmp-1;
st=i-tmp+1;
}
}

str[st+ans]=0;

printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言