POJ 3450 3080 后缀数组+二分
来源:互联网 发布:初级java程序员证书 编辑:程序博客网 时间:2024/05/08 18:42
点击打开链接
题意:问所有串的最长公共子序列
思路:后缀数组处理两个串的最长公共子序列用后缀数组非常简单就可以完成,这个多串的也一样,和两个串的处理方式相同,不多说
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int MAXN=810000;int wa[MAXN],wb[MAXN],wv[MAXN],ww[MAXN];int sa[MAXN],lcp[MAXN],Rank[MAXN],rank1[MAXN];char str1[MAXN];inline bool cmp(int *r,int a,int b,int len){ return r[a]==r[b]&&r[a+len]==r[b+len];}void construct_sa(char *str,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ww[i]=0; for(i=0;i<n;i++) ww[x[i]=str[i]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[x[i]]]=i; for(j=p=1;p<n;j<<=1,m=p){ for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++){ if(sa[i]>=j) y[p++]=sa[i]-j; } for(i=0;i<m;i++) ww[i]=0; for(i=0;i<n;i++) ww[wv[i]=x[y[i]]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[wv[i]]]=y[i]; for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void construct_lcp(int n,char *str){ for(int i=0;i<=n;i++) rank1[sa[i]]=i; int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rank1[i]-1]; if(h>0) h--; for(;j+h<n&&i+h<n;h++) if(str[i+h]!=str[j+h]) break; lcp[rank1[i]-1]=h; }}int id[MAXN],vis[4010],pos;char str2[2010];int judge(int mid,int n,int k){ memset(vis,0,sizeof(vis)); int sum=0; for(int i=0;i<k;i++){ if(lcp[i]<mid){ if(sum==0) continue; memset(vis,0,sizeof(vis));sum=0; continue; } if(vis[id[sa[i]]]==0){ sum++;vis[id[sa[i]]]=1; } if(vis[id[sa[i+1]]]==0){ sum++;vis[id[sa[i+1]]]=1; } if(sum==n){ pos=sa[i]; return 1; } } return 0;}int main(){ int n; while(scanf("%d",&n)!=-1){ if(n==0) break; int k=0; memset(id,-1,sizeof(id)); memset(str1,'\n',sizeof(str1)); for(int i=0;i<n;i++){ scanf("%s",str2); int len=strlen(str2); for(int j=0;j<len;j++){ str1[k]=str2[j]; id[k++]=i; } if(i!=n-1) str1[k++]='*'; } construct_sa(str1,k+1,300); construct_lcp(k,str1); int le=0,ri=2010; while(ri-le>1){ int mid=(le+ri)>>1; if(judge(mid,n,k)) le=mid; else ri=mid; } if(le==0) printf("IDENTITY LOST\n"); else{ for(int i=pos,j=0;j<le;j++,i++) printf("%c",str1[i]); printf("\n"); } } return 0;}
poj 3080 和上面的一样,加个组数就OK
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int MAXN=810000;int wa[MAXN],wb[MAXN],wv[MAXN],ww[MAXN];int sa[MAXN],lcp[MAXN],Rank[MAXN],rank1[MAXN];char str1[MAXN];inline bool cmp(int *r,int a,int b,int len){ return r[a]==r[b]&&r[a+len]==r[b+len];}void construct_sa(char *str,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ww[i]=0; for(i=0;i<n;i++) ww[x[i]=str[i]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[x[i]]]=i; for(j=p=1;p<n;j<<=1,m=p){ for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++){ if(sa[i]>=j) y[p++]=sa[i]-j; } for(i=0;i<m;i++) ww[i]=0; for(i=0;i<n;i++) ww[wv[i]=x[y[i]]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[wv[i]]]=y[i]; for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void construct_lcp(int n,char *str){ for(int i=0;i<=n;i++) rank1[sa[i]]=i; int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rank1[i]-1]; if(h>0) h--; for(;j+h<n&&i+h<n;h++) if(str[i+h]!=str[j+h]) break; lcp[rank1[i]-1]=h; }}int id[MAXN],vis[4010],pos;char str2[2010];int judge(int mid,int n,int k){ memset(vis,0,sizeof(vis)); int sum=0; for(int i=0;i<k;i++){ if(lcp[i]<mid){ if(sum==0) continue; memset(vis,0,sizeof(vis));sum=0; continue; } if(vis[id[sa[i]]]==0){ sum++;vis[id[sa[i]]]=1; } if(vis[id[sa[i+1]]]==0){ sum++;vis[id[sa[i+1]]]=1; } if(sum==n){ pos=sa[i]; return 1; } } return 0;}int main(){ int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); int k=0; memset(id,-1,sizeof(id)); memset(str1,'\n',sizeof(str1)); for(int i=0;i<n;i++){ scanf("%s",str2); int len=strlen(str2); for(int j=0;j<len;j++){ str1[k]=str2[j]; id[k++]=i; } if(i!=n-1) str1[k++]='*'; } construct_sa(str1,k+1,300); construct_lcp(k,str1); int le=0,ri=2010; while(ri-le>1){ int mid=(le+ri)>>1; if(judge(mid,n,k)) le=mid; else ri=mid; } if(le<3) printf("no significant commonalities\n"); else{ for(int i=pos,j=0;j<le;j++,i++) printf("%c",str1[i]); printf("\n"); } } return 0;}
0 0
- POJ 3450 3080 后缀数组+二分
- POJ 3294 后缀数组+二分
- POJ 3261 后缀数组+二分
- POJ 3294 后缀数组+二分
- POJ 3261 二分+后缀数组
- POJ 1743 后缀数组+二分
- POJ 3261 后缀数组+二分
- poj 3450 Corporate Identity(后缀数组+二分)
- POJ 3450 Corporate Identity(后缀数组+二分)
- POJ 1226 Substrings(后缀数组+二分)
- poj 3294 Life Forms(后缀数组+二分)
- POJ 1743 后缀数组+分组二分
- POJ 3261 后缀数组分组二分
- Milk Patterns+POJ+后缀数组+二分
- [后缀数组+二分] poj 1743 Musical Theme
- [后缀数组+二分] poj 3294 Life Forms
- poj 1743 后缀数组+二分判定
- POJ 1743 Musical Theme 后缀数组+二分
- 如何在自己的网站中使用KindEditor
- [从头学数学] 第212节 带着计算机去高考(四)
- Java网络爬虫基础
- 版本控制SVN
- SAX解析
- POJ 3450 3080 后缀数组+二分
- 【Java】可变参数
- C primer plus 第七章 练习4: 利用if else语句编写程序读取输入,直到#, 用一个感叹号代替每个句号,将原有的每个感叹号用两个感叹号代替,最后报告进行了多少次替代。
- STL容器总结之Vector
- IOS APP弹框检查更新 避免审核被拒
- 开根号的几类算法总结
- COE文件格式
- JavaScript和JQuery获取select的值
- STL容器总结之list