spoj220 Relevant Phrases of Annihilation
来源:互联网 发布:如何看懂棒球打击数据 编辑:程序博客网 时间:2024/05/16 01:34
题意是给n个串,求出一个最长的子串在每个串中至少出现两次。直接二分答案来判断,因为题目里要求在一个串中,两次出现的位置不能有交叉,所以这要想办法特殊处理下,大体的思路还是循环height数组,按>=当前二分长度来分组,处理一组时,用两个数组分别记录一下本组后缀在各个串中出现的最大位置和最小位置,那么如果某一个串上他的最大位置和最小位置的差大于等于当前长度了,就是两个没有交叉的匹配了。
#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cstring>using namespace std;typedef long long ll;const int maxn=220100;int s[maxn];int sa[maxn],t[maxn],t2[maxn],c[maxn];int sa2[maxn];char s1[maxn],s2[maxn];int rank[maxn],height[maxn];int l1,l2;int len,len1;int n,m,ans;int belong[maxn];inline int idx(char s){ if (s>='a' && s<='z') return s-'a'+11;}void getheight(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--; int j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) k++; height[rank[i]]=k; }}void build_ss(int m,int n){ n++; int i,*x=t,*y=t2; for (int i=0; i<m; i++) c[i]=0; for (int i=0; i<n; i++) c[x[i]=s[i]]++; for (int i=1; i<m; i++) c[i]+=c[i-1]; for (int i=n-1; i>=0; i--) sa[--c[x[i]]]=i; for (int k=1; k<=n; k<<=1) { int 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++) 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]; 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; }}int d[maxn][22];void RMQ_init(){ for (int i=1; i<=n; i++) d[i][0]=height[i]; for (int j=1; (1<<j)<=n; j++) for (int i=1; (i+(1<<j)-1)<=n; i++) d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);}int RMQ(int L,int R){ if (L>R) swap(L,R); L++; int k=0; while((1<<(k+1))<=R-L+1) k++; return min(d[L][k],d[R-(1<<k)+1][k]);}void init(){ scanf("%d",&m); n=0; int ct=1; for (int i=0; i<m; i++) { scanf("%s",s1); l1=strlen(s1); for (int j=0; j<l1; j++) belong[n]=i,s[n++]=idx(s1[j]); belong[n]=-1; s[n++]=ct++; } s[n]=0; build_ss(40,n); getheight(n);}bool check(int k){ int mi[11],mx[11]; memset(mi,0x3f,sizeof mi); memset(mx,0,sizeof mx); bool ok=false; for (int i=1; i<=n; i++) { if (height[i]>=k) { mi[belong[sa[i-1]]]=min(mi[belong[sa[i-1]]],sa[i-1]); mx[belong[sa[i-1]]]=max(mx[belong[sa[i-1]]],sa[i-1]); mi[belong[sa[i]]]=min(mi[belong[sa[i]]],sa[i]); mx[belong[sa[i]]]=max(mx[belong[sa[i]]],sa[i]); ok=true; for (int j=0; j<m; j++) if (mx[j]-mi[j]<k) ok=false; if (ok) return true; } else { memset(mi,0x3f,sizeof mi); memset(mx,0,sizeof mx); mi[belong[sa[i]]]=sa[i]; mx[belong[sa[i]]]=sa[i]; } } return false;}void slove(){ int l=1,r=10000; ans=0; while (l<r) { int mid=(l+r)>>1; if (check(mid)) ans=mid,l=mid+1; else r=mid; } printf("%d\n",ans);}int tt;int main(){// freopen("in.txt","r",stdin); scanf("%d",&tt); while(tt--) { init(); slove(); }}
0 0
- Relevant Phrases of Annihilation spoj220
- spoj220 Relevant Phrases of Annihilation
- SPOJ220:Relevant Phrases of Annihilation(后缀数组)
- [SPOJ220]PHRASES - Relevant Phrases of Annihilation(后缀数组+二分)
- Relevant Phrases of Annihilation SPOJ
- Relevant Phrases of Annihilation SPOJ
- SPOJPHRASES-Relevant Phrases of Annihilation
- spoj Relevant Phrases of Annihilation
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- SPOJ220---Relevant Phrases of Annihilation(后缀数组+二分,对后缀分组)
- SPOJ PHRASES Relevant Phrases of Annihilation
- SPOJ PHRASES 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 PHRASES Relevant Phrases of Annihilation 后缀数组
- spoj 220 PHRASES - Relevant Phrases of Annihilation(后缀数组)
- 嵌入式Linux中让应用程序自动启动
- 词项词典及倒排记录表
- poj2785(折半枚举)
- 【自动化测试技术QTP基础系列十一】---Action之间的参数传递
- spring 中 applicationEvent的使用
- spoj220 Relevant Phrases of Annihilation
- Word 中统一改变公式格式
- 谱密度,功率谱,能量谱密度
- 数据交换工具Kettle
- test
- Oracle的SGA
- 发布项目到Nexus私服
- 关心的问题之:JMS
- JavaScript学习笔记(一)基本概念及语法