UVa11107 Lifeform
2016-05-06 16:33
113 查看
题目链接
UVa11107 Lifeform题解
学了高大上的后缀数组但是还是不怎么会用,关键是版子最开始打错了,害得我必须再重新理解一遍才能找出bug,开始以为是memset(sa,0,sizeof(sa))这句少写了但是并不是这样.话说字符串的题特别容易RE.这道题二分答案然后后缀数组,先将字符串合并,每个串后加一个奇怪的不相同的字符,二分长度,然后在height数组中去找,每次当当前height值小于ans的时候再开一段,这时检查前一段是否符合要求.具体方法先用一个idx[i]表示字符串中第i个属于第几个字符串然后用flag[i]来表示有没有在第i个字符串中出现,最后统计一下flag==1的个数,若>n/2则return true;复杂度更低的O(n*L)正准备学.
代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=100*2+10; const int MAXLEN=10000000*2; int idx[MAXLEN],n; struct SuffixArray{ int s[MAXLEN]; int sa[MAXLEN],height[MAXLEN],rank[MAXLEN],n; int t[MAXLEN*2],t2[MAXLEN*2]; long long cnt[MAXLEN]; SuffixArray(){n=0;} void clear(){n=0;} void build_sa(int m){ int i,*x=t,*y=t2; for(i=0;i<m;i++) cnt[i]=0; for(i=0;i<n;i++) cnt[x[i]=s[i]]++; for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i;//血的教训,妈蛋这个等号害了我一整天 for(int k=1,p=0;k<n;k <<=1) { p=0; 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++) cnt[i]=0; for(i=0;i<n;i++) cnt[x[y[i]]]++; for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1; else x[sa[i]]=p++; if(p>=n) break; m=p; } } void build_height() { int k=0; for(int i=0;i<n;i++) rank[sa[i]]=i; for(int i=0;i<n;i++) { if(k) k--; if(!rank[i]) continue; int j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) k++; height[rank[i]]=k; } } }SA; inline void add(int ch,int id){ idx[SA.n]=id; SA.s[SA.n++]=ch; } int flag[maxn]; inline int check(int ans){ int check_clock=1; memset(flag,0,sizeof(flag)); for(int i=1;i<SA.n;i++) { if(SA.height[i]>=ans) { flag[idx[SA.sa[i]]]=check_clock; flag[idx[SA.sa[i-1]]]=check_clock; } else { int cnt=0; for(int j=0;j<n;j++) if(flag[j]==check_clock) cnt++; if(cnt>n/2) return true; flag[idx[SA.sa[i]]]=++check_clock; } } return false; } inline void print_ans(int l,int r){ for(int i=l;i<=r;i++) printf("%c",SA.s[i]+'a'-1); printf("\n"); } inline void print(int ans){ int check_clock=1; memset(flag,0,sizeof(flag)); for(int i=1;i<SA.n;i++) { if(SA.height[i]>=ans) { flag[idx[SA.sa[i]]]=check_clock; flag[idx[SA.sa[i-1]]]=check_clock; } else { int cnt=0; for(int j=0;j<n;j++) if(flag[j]==check_clock) cnt++; if(cnt>n/2) print_ans(SA.sa[i-1],SA.sa[i-1]+ans-1); flag[idx[SA.sa[i]]]=++check_clock; } } } char s[1000+10]; int kase=0; int main() { int maxlen; while(scanf("%d",&n)==1&&n) { if(kase++) printf("\n"); SA.clear(); maxlen=0; for(int i=0;i<n;i++){ scanf("%s",s); int l=strlen(s); maxlen=max(maxlen,l); for(int j=0;j<l;j++) add(s[j]-'a'+1,i); add(100+i,n); } if(n==1) { printf("%s\n",s);continue; } SA.build_sa(101+n); SA.build_height(); int l=1,r=maxlen,ans=0; while(l<=r) { int mid=((l+r)>>1); if(check(mid)) ans=mid,l=mid+1; else r=mid-1; } if(ans)print(ans); else printf("?\n"); } return 0; }
相关文章推荐
- CSS默认可继承样式详解
- 前端上传组件Plupload
- CSS3中的动画,animation、transition和transform属性的运用
- 子元素取行列标题
- js页面跳转整理
- html 锚点链接 图像热区链接
- javascript查找DOM元素的方法总结
- 判断是否字符串是否是JSON
- bootstrap data-original-title
- Effective Java学习--第21条:用函数对象表示策略
- JSON-lib使用手册
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包
- Javascript闭包