UVa11107 Lifeform
来源:互联网 发布:阴阳师辅助软件ios 编辑:程序博客网 时间:2024/06/14 22:34
题目链接
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;}
1 0
- UVa11107 Lifeform
- UVa11107
- UVa11107 后缀数组
- uva11107 后缀数组
- 后缀数组(UVa11107)
- Uva11107——后缀数组
- UVA11107 Life Froms 后缀数组
- uva11107 - Life Forms 后缀数组
- UVA11107 后缀数组(new模板)
- 例题3.17 生命的形式 UVa11107
- 后缀数组+LCP+多个串找公共子序列+uva11107
- 【模板】素数筛选
- Java---注解、类加载器-加强-实现运行任意目录下class中加了@MyTest的空参方法
- saltstack 远程执行脚本
- 第9周项目1-深复制体验(1)
- 正则表达式
- UVa11107 Lifeform
- iOS上架之内购
- Permission Denial: not allowed to send broadcast android.intent.action.MEDIA_MOUNTED解决方法
- Spark 集群与数据集RDD
- red5源码分析---6
- C++11中的线程同步(简单测试)
- 【SSH网上商城项目实战07】Struts2和Json的整合
- 微信开发-SHA1算法
- 数据加序号,ireport里面