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 }

浙公网安备 33010602011771号