[SPOJ220 Relevant Phrases of Annihilation]
2012-03-29 21:57
369 查看
[关键字]:后缀数组 字符串
[题目大意]:给定n 个字符串,求在每个字符串中至少出现两次且不重叠的最长子串。
//======================================================================
[分析]:做法和POJ3294大同小异,也是先将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符(且小于它们)隔开,最后加上一个最小的数求后缀数组。然后二分答案,再将后缀分组。判断的时候,要看是否有一组后缀在每个原来的字符串中至少出现两次,并且在每个原来的字符串中,后缀的起始位置的最大值与最小值之差是否不小于当前答案(判断能否做到不重叠,如果题目中没有不重叠的要求,那么不用做此判断)。
[代码]:
View Code
[题目大意]:给定n 个字符串,求在每个字符串中至少出现两次且不重叠的最长子串。
//======================================================================
[分析]:做法和POJ3294大同小异,也是先将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符(且小于它们)隔开,最后加上一个最小的数求后缀数组。然后二分答案,再将后缀分组。判断的时候,要看是否有一组后缀在每个原来的字符串中至少出现两次,并且在每个原来的字符串中,后缀的起始位置的最大值与最小值之差是否不小于当前答案(判断能否做到不重叠,如果题目中没有不重叠的要求,那么不用做此判断)。
[代码]:
View Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int MAXN=100100; const int MAXL=10010; int n,x,test,df,r,l; int top[MAXN],sa[MAXN],rank[MAXN],temp[MAXN],height[MAXN]; int s[MAXN],belong[MAXN],v[15],Max[15],Min[15]; char s1[MAXL]; void Make() { int i,j,len,m; m=n<256?256:n; memset(top,0,m*sizeof(int)); for (i=0;i<n;++i) ++top[rank[i]=s[i]&0xff]; for (i=1;i<m;++i) top[i]+=top[i-1]; for (i=0;i<n;++i) sa[--top[rank[i]]]=i; for (len=1;len<n;len<<=1) { for (i=0;i<n;++i) { j=sa[i]-len; if (j<0) j+=n; temp[top[rank[j]]++]=j; } sa[temp[top[0]=0]]=j=0; for (i=1;i<n;++i) { if (rank[temp[i]]!=rank[temp[i-1]] || rank[temp[i]+len]!=rank[temp[i-1]+len]) top[++j]=i; sa[temp[i]]=j; } memcpy(rank,sa,m*sizeof(int)); memcpy(sa,temp,m*sizeof(int)); if (j>=n-1) break; } } void Lcp() { int i,j,k; for (j=rank[height[i=k=0]=0];i<n-1;++i,++k) while (k>=0 && s[i]!=s[sa[j-1]+k]) height[j]=(k--),j=rank[sa[j]+1]; } bool Judge(int limit) { int i,j; memset(v,0,sizeof(v)); memset(Min,100,sizeof(Min)); memset(Max,200,sizeof(Max)); for (i=1;i<=n;++i) { if (height[i]<limit) { for (j=1;j<=x;++j) if (v[j]<2 || Max[j]-Min[j]<limit) break; if (j==x+1) return 1; memset(v,0,sizeof(v)); memset(Max,200,sizeof(Max)); memset(Min,100,sizeof(Min)); } ++v[belong[sa[i]]]; Max[belong[sa[i]]]=Max[belong[sa[i]]]>sa[i]?Max[belong[sa[i]]]:sa[i]; Min[belong[sa[i]]]=Min[belong[sa[i]]]<sa[i]?Min[belong[sa[i]]]:sa[i]; } return 0; } void Solve() { int ans=0,mid,l=1,r=10100; while (l<=r) { mid=(l+r)/2; if (Judge(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); } int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d",&test); while (test--) { n=df=0; scanf("%d",&x); for (int i=1;i<=x;++i) { scanf("%s",s1); int len=strlen(s1); for (int j=0;j<len;++j) s[n+j]=(int)s1[j]+10,belong[n+j]=i; s[n+len]=++df,belong[n+len]=0; n+=len+1; } s[n-1]=0; Make(); Lcp(); /*printf("%d\n",n); for (int i=0;i<n;++i) printf("%d ",height[i]); printf("\n"); for (int i=0;i<n;++i) printf("%d ",belong[i]); printf("\n");*/ height =0; Solve(); } return 0; }
相关文章推荐
- [spoj][220][Relevant Phrases of Annihilation]
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分)
- SPOJ 220 . Relevant Phrases of Annihilation(后缀数组)
- spoj 220 Relevant Phrases of Annihilation(每个字符串至少出现两次且不重叠的最长子串)
- spoj 220 Relevant Phrases of Annihilation (后缀数组应用)
- SPOJ-220-Relevant Phrases of Annihilation
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组)
- 【SPOJ】220 Relevant Phrases of Annihilation
- SPOJ 220 Relevant Phrases of Annihilation (后缀数组)
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- spoj 220 Relevant Phrases of Annihilation (后缀数组 每个串中都至少出现两次的不重叠最长子串)
- [SPOJ220]PHRASES - Relevant Phrases of Annihilation(后缀数组+二分)
- 字符串练习题:SPOJ 220 Relevant Phrases of Annihilation(后缀数组加二分)
- SPOJ 220 PHRASES Relevant Phrases of Annihilation 后缀数组
- spoj220 Relevant Phrases of Annihilation
- 【SPOJ 220】 PHRASES - Relevant Phrases of Annihilation
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- Relevant Phrases of Annihilation spoj220
- SPOJ220:Relevant Phrases of Annihilation(后缀数组)
- spoj 220 PHRASES - Relevant Phrases of Annihilation(后缀数组)