POJ 2774 后辍数组 --> 最长公共子序列

这题是后辍数组的一个应用。

很2B的,到现在还没理解后辍数组的形成原理。IQ不够,人也不勤快。唉。

 

这题很明显的是Height数组的应用,height[i]=common_prefix(sa[i-1],sa[i])

我们将str1和str2拼接起来。形成str1+'#'+str2+'&'的形式。

然后求出sa[i-1]和sa[i](sa[i-1]和sa[i]属于不同的串)的最长公共前辍,就是题目的最后答案。

 

WA Point:

没有在join串的末尾加上特殊标记符,导致求height数组的时候溢出了。。。>_<。。。

 

P.S. 这题MS加数据了,Discuss里面说的那种特殊情况是不存在的。。。

E.g. abcde    abxxxcdeab    的答案是3(cde) 而不是 5(cde_ab , cdeab)

 

View Code
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <set>
  8 #include <bitset>
  9 
 10 using namespace std;
 11 
 12 #define print(x) cout<<x<<endl
 13 #define input(x) cin>>x
 14 #define SIZE 100010
 15 #define N (SIZE<<1)+5
 16 
 17 char join[N],loc[N];
 18 int sa[N],rank[N],height[N];
 19 int len;
 20 
 21 int cmpSuffix(const void *a,const void *b)
 22 {
 23     int ta=*(int*)a,tb=*(int*)b;
 24     return join[ta]-join[tb];
 25 }
 26 
 27 bool cmp(int a,int b,int spow)
 28 {
 29     if(rank[a]!=rank[b]) return 1;
 30     else
 31     {
 32         if(rank[a+spow]!=rank[b+spow]) return 1;
 33         else return 0;
 34     }
 35 }
 36 
 37 void makeSuffixArray()
 38 {
 39     for(int i=0;i<len;i++) sa[i]=i;
 40     qsort(sa,len,sizeof(int),cmpSuffix);
 41     for(int i=0,j=0;i<len;i++)
 42     {
 43         if(i>0 and join[sa[i]]!=join[sa[i-1]]) j++;
 44         rank[sa[i]]=j;
 45     }
 46 
 47     int tmp[N],nextRank[N],mark[N];
 48     memset(mark,0,sizeof(mark));
 49     for(int spow=1;spow<len;spow<<=1)
 50     {
 51         memset(tmp,0,sizeof(tmp));
 52         for(int i=0;i<len;i++)
 53         {
 54             if(sa[i]+spow<len) tmp[rank[sa[i]+spow]]++;
 55             else tmp[rank[sa[i]]]++;
 56         }
 57         for(int i=1;i<len;i++) tmp[i]+=tmp[i-1];
 58         for(int i=len-1;i>=0;i--)
 59         {
 60             if(sa[i]+spow<len) mark[--tmp[rank[sa[i]+spow]]]=sa[i];
 61             else mark[--tmp[rank[sa[i]]]]=sa[i];
 62         }
 63         memset(tmp,0,sizeof(tmp));
 64         for(int i=0;i<len;i++) tmp[rank[mark[i]]]++;
 65         for(int i=1;i<len;i++) tmp[i]+=tmp[i-1];
 66         for(int i=len-1;i>=0;i--) sa[--tmp[rank[mark[i]]]]=mark[i];
 67         for(int i=0,j=0;i<len;i++)
 68         {
 69             if(i>0&&cmp(sa[i],sa[i-1],spow)!=0) j++;
 70             nextRank[sa[i]]=j;
 71         }
 72         memcpy(rank,nextRank,sizeof(rank));
 73     }
 74 }
 75 
 76 void makeHeight()
 77 {
 78     int k=0;
 79     for(int i=0,j;i<len;i++)
 80     {
 81         if(rank[i]==0) height[rank[i]]=k=0;
 82         else
 83         {
 84             if(k>0) k--;
 85             j=sa[rank[i]-1];
 86             while(join[i+k]==join[j+k])
 87             {
 88                 //print(i<<' '<<j);
 89                 k++;
 90             }
 91             height[rank[i]]=k;
 92         }
 93     }
 94 }
 95 
 96 
 97 int main()
 98 {
 99     freopen("input.txt","r",stdin);
100     char *p=join;
101     int sz;
102     scanf("%s",p);
103     sz=strlen(p);
104     for(int i=0;i<sz;i++) loc[i]=1;
105     p+=sz;
106     *(p++)='#';
107     scanf("%s",p);
108     sz=strlen(p);
109     p+=sz;
110     *(p++)='$';
111     //print(join);
112     len=strlen(join);
113     makeSuffixArray();
114     makeHeight();
115     
116     //for(int i=0;i<len;i++)
117     //{
118     //    puts(&join[sa[i]]);
119     //}
120     int ans=-1;
121     for(int i=1;i<len;i++)
122     {
123         if(loc[sa[i]]^loc[sa[i-1]])
124         {
125             ans=max(ans,height[i]);
126         }
127     }
128     print(ans);
129     return 0;
130 }

posted on 2012-07-15 00:37  Wizmann  阅读(284)  评论(0)    收藏  举报

导航