您的位置:首页 > 其它

后缀数组详解

2017-08-30 15:19 344 查看
这是一部分,以后还会更新的
 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 10000
using namespace std;

char s[maxn],s1[maxn];
int sa[maxn];/***sa[第几大]=第几位开始的后缀***/
int Rank[maxn];/***rank[第几位开始的后缀]=第几大***/
int t[maxn],t2[maxn],c[maxn],n;

void build_sa(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;
/**直接利用sa数组排序第二关键字**/
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];
/**根据sa和y数组计算新的x数组**/
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;/**以后即使继续倍增,sa也不会改变,退出**/
m=p;/**下次基数排序的最大值**/
}
}

int m;
int cmp_suffix(char *pattern,int p)
{
return strncmp(pattern,s+sa[p],m);
/***************************
用 法: int strncmp(char *str1, char *str2, int maxlen);
说明:此函数功能即比较字符串str1和str2的前maxlen个字符。
如果前maxlen字节完全相等,返回值就=0;
在前maxlen字节比较过程中,如果出现str1
与str2
不等,
则返回(str1
-str2
)。
****************************/
}

int find(char *p)
{
m=strlen(p);
if(cmp_suffix(p,0)<0)return -1;/**下界为第0个后缀**/
if(cmp_suffix(p,n-1)>0)return -1;/**上界为第n-1个后缀**/
int l=0,r=n-1;
while(r>=l)/**二分判断是否有该后缀与P的公共前缀=p的长度**/
{
int m=l+(r-l)/2;
int res=cmp_suffix(p,m);
if(!res)return m;
if(res<0)r=m-1;else l=m+1;
}
return -1;
}

int main()
{
scanf("%s",s);
n=strlen(s);
build_sa(300);/**char的最大字符值**/
scanf("%s",s1);
cout<<find(s1);/**从s中查找s1**/
return 0;
}


 

 

 

下面这个是基础版,常数会大些,复杂度不变

1 #include <iostream>
2 #include <string>
3 #include <cstring>
4 #include <algorithm>
5 #include <cstdio>
6 #define maxlen 1000
7 #define maxn 10000
8
9 using namespace std;
10
11 char s[maxlen],s1[maxlen];
12 int sa[maxn],tsa[maxn],Rank[maxn],trank[maxn],sum[maxn];
13 int n,m;
14
15 void sorting(int j)
16 {
17     memset(sum,0,sizeof(sum));
18     for(int i=1;i<=n;i++)sum[Rank[i+j]]++;
19     for(int i=1;i<=maxlen;i++)sum[i]+=sum[i-1];
20     for(int i=n;i!=0;i--)tsa[sum[Rank[i+j]]--]=i;
21
22     memset(sum,0,sizeof(sum));
23     for(int i=1;i<=n;++i)sum[Rank[i]]++;
24     for(int i=1;i<=maxlen;++i)sum[i]+=sum[i-1];
25     for(int i=n;i!=0;i--)sa[sum[Rank[tsa[i]]]--]=tsa[i];
26 }
27
28 void build_sa()
29 {
30     int p;
31     for(int i=0;i!=n;++i)trank[i+1]=s[i];
32     for(int i=1;i<=n;++i)sum[trank[i]]++;
33     for(int i=1;i<=maxlen;++i)sum[i]+=sum[i-1];
34     for(int i=n;i!=0;i--)sa[sum[trank[i]]--]=i;
35     Rank[sa[1]]=1;
36     for(int i=2,p=1;i<=n;++i)
37     {
38         if(trank[sa[i]]!=trank[sa[i-1]])p++;
39         Rank[sa[i]]=p;
40     }
41     for(int j=1;j<=n;j*=2)
42     {
43         sorting(j);
44         trank[sa[1]]=1;p=1;
45         for(int i=2;i<=n;++i)
46         {
47             if((Rank[sa[i]]!=Rank[sa[i-1]]) || (Rank[sa[i]+j]!=Rank[sa[i-1]+j]))p++;
48             trank[sa[i]]=p;
49         }
50         for(int i=1;i<=n;++i)Rank[i]=trank[i];
51     }
52 }
53
54 void init()
55 {
56     memset(sum,0,sizeof(sum));
57     memset(Rank,0,sizeof(Rank));
58     memset(trank,0,sizeof(trank));
59     memset(sa,0,sizeof(sa));
60     memset(tsa,0,sizeof(tsa));
61 }
62
63 int cmp_suffix(char *pattern,int p){return strncmp(pattern,s+sa[p]-1,m);}
64
65 int finds(char *p)
66 {
67     m=strlen(p);
68     if(cmp_suffix(p,1)<0)return -1;
69     if(cmp_suffix(p,n)>0)return -1;
70     int l=1,r=n;
71     while(r>=l)
72     {
73         int m=l+(r-l)/2;
74         int res=cmp_suffix(p,m);
75         if(!res)return m;
76         if(res<0)r=m-1;else l=m+1;
77     }
78     return -1;
79 }
80
81 int main()
82 {
83     init();
84     scanf("%s",s);
85     n=strlen(s);
86     build_sa();
87     scanf("%s",s1);
88     cout<<finds(s1);
89     return 0;
90 }


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: