RoNgDaZhOnG

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

这次的后缀数组写的成熟点,也好看点,以后生成后缀数组的话就用这里的build_sa()函数吧
rank[i]表示以i为起点的后缀在sa数组中的位置,height[i]则表示sa[i]和sa[i-1]的最长公共前缀的长度。
有一个定理:height[rank[i]]>=height[rank[i-1]-1,具体证明可以看刘汝佳的白书。
根据这个定理,每次for i=1 to n,每次根据height[rank[i-1]]求出height[rank[i]],减少比较次数。
sa[i]和sa[j]的最长公共前缀 = min{height[i+1],height[i+2]······,height[j] }(假设i<j)

还有,一定要记住求后缀数组时我的order数组不能直接更改,要当一轮顺序确定后再更改order的值,否则将出现很难察觉的错误。就因为这个,调程序到这么晚。。好苦。

对于这道题Codevs3160,直接将两个字符串合在一起,中间插入个特殊字符(两个字符串中都没有的),就再求后缀数组,再用后缀数组求最长公共前缀,再判断下每个前缀长度是否为合法答案即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 int cmp_len=1,S_Len;
 8 char S[300000];
 9 int order[500000],height[300000],rank[300000];
10 struct A_Suffix{
11        int st;
12        friend bool operator < (const A_Suffix a,const A_Suffix b){
13               if(cmp_len==1) return S[a.st]<S[b.st];
14               if(order[a.st]!=order[b.st]) return order[a.st]<order[b.st];
15               return order[a.st+cmp_len/2]<order[b.st+cmp_len/2];
16        }
17        friend bool operator ==(const A_Suffix a,const A_Suffix b){
18               if(cmp_len==1) return S[a.st]==S[b.st];
19               return (order[a.st]==order[b.st] && order[a.st+cmp_len/2]==order[b.st+cmp_len/2]);
20        }
21 }sa[500000];
22 void build_sa(){
23      int order2[500000];
24      for(int i=0;i<S_Len;i++) sa[i]=((A_Suffix){i});
25      while(1){
26               sort(sa,sa+S_Len);
27               int k = order2[sa[0].st] = 1;
28               for(int i=1;i<S_Len;i++){
29                       if(!(sa[i]==sa[i-1])) k++;
30                       order2[sa[i].st]=k;
31               }
32               for(int i=0;i<S_Len;i++) order[i]=order2[i];
33               if(cmp_len>=S_Len) break;
34               cmp_len*=2;
35      }
36 }
37 void get_height(){
38      int h=0;
39      for(int i=0;i<S_Len;i++) rank[sa[i].st]=i;
40      for(int i=0;i<S_Len;i++){
41              if(h) h--;
42              if(rank[i]==0) {h=0;continue;}
43              int j=sa[rank[i]-1].st;
44              while(S[i+h]==S[j+h])  h++;  //height[rank[i]]>=height[rank[i-1]]-1
45              height[rank[i]] = h;
46      }
47 }              
48                                                                                                    
49 int main(){    
50     scanf("%s",S);
51     int mid=strlen(S);
52     S[mid]='~';
53     scanf("%s",S+strlen(S));
54     S_Len=strlen(S);
55     build_sa();get_height();
56     int ans=0;
57     for(int i=1;i<S_Len;i++){
58             if(sa[i].st<mid && sa[i-1].st>mid) ans=max(ans,height[i]);
59             if(sa[i].st>mid && sa[i-1].st<mid) ans=max(ans,height[i]);
60     }
61     printf("%d\n",ans);
62     return 0;
63 }

 

posted on 2017-03-16 22:20  学无止境-1980  阅读(168)  评论(0编辑  收藏  举报