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 }

你可能感兴趣的:(poj)