/* ***********************************************
Author :xianxingwuguan
Created Time :2014/1/19 11:14:49
File Name :3.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn=100010;
char str[maxn];
int sa[maxn],height[maxn],t[maxn],t2[maxn],c[maxn],rank[maxn];
void da(char *str,int n,int m)
{
int i,j,k,p,*x=t,*y=t2;
for(i=0;i<m;i++)c[i]=0;
for(i=0;i<n;i++)c[x[i]=str[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(k=1;k<=n;k<<=1)
{
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=1;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 calheight(char *s,int n)
{
int i,j,k=0;
for(i=0;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<=n;i++)
{
if(k)k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
int Log[maxn];
int best[20][maxn];
void initrmq(int n)
{
int i,j;
Log[0]=-1;
for(i=1;i<=n;i++)Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1;
for(i=1;i<=n;i++)best[0][i]=height[i];
for(i=1;i<=Log[n];i++)
for(j=1;j+(1<<i)-1<=n;j++)
best[i][j]=min(best[i-1][j],best[i-1][j+(1<<(i-1))]);
}
int lcp(int a,int b)
{
a=rank[a];b=rank[b];
if(a>b)swap(a,b);
a++;
int t=Log[b-a+1];
return min(best[t][a],best[t][b-(1<<t)+1]);
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
int i,j,k,m,n;
while(~scanf("%s",str))
{
n=strlen(str);
da(str,n+1,300);
calheight(str,n);
initrmq(n);
cout<<"sa:";for(i=0;i<=n;i++)cout<<sa[i]<<" ";cout<<endl;
cout<<"rank:";for(i=0;i<=n;i++)cout<<rank[i]<<" ";cout<<endl;
cout<<"height:";for(i=0;i<=n;i++)cout<<height[i]<<" ";cout<<endl;
while(cin>>i>>j)
{
if(i==0&&j==0)break;
cout<<lcp(i,j)<<endl;
}
}
return 0;
}
/*
C:\Windows\system32\cmd.exe /c 3
aabaaaab
sa:8 3 4 5 0 6 1 7 2
rank:4 6 8 1 2 3 5 7 0
height:0 0 3 2 3 1 2 0 1
*/
后缀数组测试1
最新推荐文章于 2019-10-17 13:20:36 发布