POJ-3294 Life Forms 后缀数组
2013-04-25 23:58
627 查看
题目链接:http://poj.org/problem?id=3294
多个串中,出现次数为k次的最长公共子串的个数,并且输出。
一般的算法就是后缀数组加二分,复杂度O(n*logn)。其实也可以和POJ3415一样维护一个栈,思想都是差不多的,维护一个单调递增的栈,每到一个height[i]时,先保证栈单调递增并且统计个数sum,然后height[i]再与当前最优值比较,如果大于最优值,那么看sum是否大于k,如果大于则更新最优值。平均复杂度O(n)。
二分代码:
多个串中,出现次数为k次的最长公共子串的个数,并且输出。
一般的算法就是后缀数组加二分,复杂度O(n*logn)。其实也可以和POJ3415一样维护一个栈,思想都是差不多的,维护一个单调递增的栈,每到一个height[i]时,先保证栈单调递增并且统计个数sum,然后height[i]再与当前最优值比较,如果大于最优值,那么看sum是否大于k,如果大于则更新最优值。平均复杂度O(n)。
二分代码:
//STATUS:C++_AC_375MS_4328KB #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<iostream> #include<string> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> using namespace std; #define LL long long #define pii pair<int,int> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define PI acos(-1.0) const int N=101010,INF=0x3f3f3f3f,MOD=10000,STA=8000010; const LL LNF=0x3f3f3f3f3f3f3f3f; const double DNF=1e13; // void swap(int& a,int& b){int t=a;a=b;b=t;} void swap(LL& a,LL& b){LL t=a;a=b;b=t;} // int num ; int sa ,t1 ,t2 ,c ,rank ,height ,vis ,ma ; int n,m,T; void build_sa(int s[],int n,int m) { int i,k,p,*x=t1,*y=t2; //第一轮基数排序 for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(k=1;k<=n;k<<=1){ p=0; //直接利用sa数组排序第二关键字 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++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; //根据sa和x数组计算新的x数组 swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; //已经排好序,直接退出 m=p; //下次基数排序的最大值 } } void getHeight(int s[],int n) { int i,j,k=0; for(i=0;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;i++){ if(k)k--; j=sa[rank[i]-1]; while(s[i+k]==s[j+k])k++; height[rank[i]]=k; } } int binary(int l,int r) { int i,j,mid,ok,ret,k,cnt; mem(vis,0);k=1; while(l<=r){ mid=(l+r)>>1; cnt=1;ok=0; vis[ma[sa[1]]]=k; for(i=2;i<=n;i++){ if(height[i]>=mid){ if(vis[ma[sa[i]]]!=k)vis[ma[sa[i]]]=k,cnt++; } else { if(cnt>T/2){ok=1;break;} k++;cnt=1; vis[ma[sa[i]]]=k; } } k++; if(cnt>T/2)ok=1; if(ok)ret=mid,l=mid+1; else r=mid-1; } return ret; } int main() { // freopen("in.txt","r",stdin); int i,j,cnt,ans,k,t; char s ; while(~scanf("%d",&T) && T) { n=0;cnt=130; for(i=0;i<T;i++){ scanf("%s",s); for(j=0;s[j];j++){ ma =i; num[n++]=s[j]-'a'+1; } ma =i; num[n++]=cnt++; } num =0; m=cnt; build_sa(num,n+1,m); getHeight(num,n); ans=binary(0,1001); if(ans){ if(T==1){ printf("%s\n\n",s); continue; } mem(vis,0); k=1;cnt=1; vis[ma[sa[1]]]=1; for(i=2;i<=n;i++){ if(height[i]>=ans){ if(vis[ma[sa[i]]]!=k)vis[ma[sa[i]]]=k,cnt++; } else { if(cnt>T/2){ for(j=sa[i-1],t=ans;t--;j++) printf("%c",num[j]+'a'-1); putchar('\n'); } k++;cnt=1; vis[ma[sa[i]]]=k; } } if(cnt>T/2){ for(j=sa[i-1],t=ans;t--;j++) printf("%c",num[j]+'a'-1); putchar('\n'); } } else printf("?\n"); putchar('\n'); } return 0; }
相关文章推荐
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms 后缀数组
- poj 3294 Life Forms 后缀数组
- POJ3294——Life Forms 后缀数组
- poj3294 Life Forms(后缀数组)
- POJ 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms(后缀数组)
- POJ 3294 Life Forms(后缀数组)
- poj 3294 Life Forms 求n(n>1)个字符串的最长的一个子串 后缀数组
- poj 3294 Life Forms(后缀数组)
- poj 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组)
- POJ 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组)
- poj 3294 Life Forms (后缀数组应用)
- poj 3294(Life Forms) 2分+ 后缀数组
- poj 3294 后缀数组
- [后缀数组+二分] poj 3294 Life Forms
- 【POJ】3294 Life Forms