首页 > 代码库 > Life Forms
Life Forms
poj3294:http://poj.org/problem?id=3294
题意:就是求n个串的中一个最大的子串,这个子串在超过n/2的串中出现。
题解:这是一道好题。首先一种解法就是用后缀数组来搞,首先把n个串拼接起来,然后,每个串后面加上一个特殊的额字符,然后求后缀数组以及h数组,然后一个很经典的做法就是二分长度,找到满足条件的长度,然后输出答案。这一题恶心了我一天。各种错误。1,统计的时候出错2是memset的数组开打了,结果T了,3是答案数组没有清空,结果wa了4特殊清空n==1时候没有考虑。printf(%s)是从起始位置输出字符直到遇到\0为止,合法,
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=110010; 6 char str[maxn]; 7 int id[maxn]; 8 int wa[maxn],wb[maxn],wv[maxn],wn[maxn],a[maxn],sa[maxn]; 9 int cmp(int* r,int a,int b,int l){ 10 return r[a]==r[b]&&r[a+l]==r[b+l]; 11 } 12 //n为字符串长度,m为字符的取值范围,r为字符串。后面的j为每次排序时子串的长度 13 void DA(int* r,int* sa,int n,int m){ 14 int i,j,p,*x=wa,*y=wb,*t; 15 ///对R中长度为1的子串进行基数排序 16 for(i=0; i<m; i++)wn[i]=0; 17 for(i=0; i<n; i++)wn[x[i]=r[i]]++; 18 for(i=1; i<m; i++)wn[i]+=wn[i-1]; 19 for(i=n-1; i>=0; i--)sa[--wn[x[i]]]=i; 20 for(j=1,p=1; p<n; j*=2,m=p){ 21 //利用了上一次基数排序的结果,对待排序的子串的第二关键字进行了一次高效地基数排序 22 for(p=0,i=n-j; i<n; i++)y[p++]=i; 23 for(i=0; i<n; i++)if(sa[i]>=j)y[p++]=sa[i]-j; 24 ///基数排序 25 for(i=0; i<n; i++)wv[i]=x[y[i]]; 26 for(i=0; i<m; i++)wn[i]=0; 27 for(i=0; i<n; i++)wn[wv[i]]++; 28 for(i=1; i<m; i++)wn[i]+=wn[i-1]; 29 for(i=n-1; i>=0; i--)sa[--wn[wv[i]]]=y[i]; 30 ///当p=n的时候,说明所有串都已经排好序了 31 ///在第一次排序以后,rank数组中的最大值小于p,所以让m=p 32 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++) 33 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 34 } 35 return; 36 } 37 ///后缀数组 计算height数组 38 /** 39 height数组的值应该是从height[1]开始的,而且height[1]应该是等于0的。 40 原因是,+因为我们在字符串后面添加了一个0号字符,所以它必然是最小的 41 一个后缀。而字符串中的其他字符都应该是大于0的(前面有提到,使用倍 42 增算法前需要确保这点),所以排名第二的字符串和0号字符的公共前缀 43 (即height[1])应当为0.在调用calheight函数时,要注意height数组的范 44 围应该是[1..n]。所以调用时应该是calheight(r,sa,n) 45 而不是calheight(r,sa,n+1)。*/ 46 int rank[maxn],height[maxn]; 47 void calheight(int* r,int* sa,int n){ 48 int i,j,k=0; 49 for(i=1; i<=n; i++)rank[sa[i]]=i; 50 for(i=0; i<n; height[rank[i++]]=k) 51 for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++); 52 return; 53 } 54 int t; 55 char temp[1002]; 56 bool vis[102]; 57 bool getsum(int len,int n){ 58 memset(vis,0,sizeof(vis)); 59 int counts=0; 60 for(int i=2;i<=n;i++){ 61 if(height[i]<len){ 62 memset(vis,0,sizeof(vis)); 63 counts=0; 64 } 65 else { 66 if(!vis[id[sa[i-1]]]){ 67 vis[id[sa[i-1]]]=1;counts++; 68 } 69 if(!vis[id[sa[i]]]){ 70 vis[id[sa[i]]]=1;counts++; 71 } 72 if(counts>t/2){ 73 return true; 74 } 75 } 76 } 77 return false; 78 } 79 char www[maxn]; 80 void print(int len,int n){ 81 memset(vis,0,sizeof(vis)); 82 int counts=0,tag=0; 83 for(int i=2;i<=n;i++){ 84 if(height[i]<len){ 85 memset(vis,0,sizeof(vis)); 86 counts=0; 87 tag=0; 88 } 89 else { 90 if(!vis[id[sa[i-1]]]){ 91 vis[id[sa[i-1]]]=1;counts++; 92 } 93 if(!vis[id[sa[i]]]){ 94 vis[id[sa[i]]]=1;counts++; 95 } 96 if(counts>t/2&&!tag){ 97 tag=1; 98 for(int j=0;j<len;j++){ 99 www[j]=a[sa[i]+j]-1+‘a‘;100 }101 www[len]=‘\0‘;//这里由于自己没有加上这一句,结果wa了,因为www之前没有清空102 printf("%s\n",www);103 }104 }105 }106 107 }108 char temp2[1002];109 int main(){110 int sg=1;111 while(~scanf("%d",&t)&&t){112 if(sg>1)puts("");113 sg=2;114 memset(temp2,0,sizeof(temp2));115 int sumlen=0,tp=50,r=0;116 for(int i=1;i<=t;i++){117 memset(temp,0,sizeof(temp));118 scanf("%s",temp);119 if(i==1)120 strcpy(temp2,temp);121 int len=strlen(temp);122 r=max(r,len);123 for(int j=0;j<len;j++){124 a[sumlen+j]=temp[j]-‘a‘+1;125 id[sumlen+j]=i;126 }127 sumlen+=len;128 a[sumlen]=tp++;129 id[sumlen++]=i;130 }131 id[sumlen]=t;132 DA(a,sa,sumlen+1,260);133 calheight(a,sa,sumlen);134 int ans=0,l=0;135 while(l<=r){136 int mid=(l+r)/2;137 if(getsum(mid,sumlen)){138 l=mid+1;139 ans=mid;140 }141 else{142 r=mid-1;143 }144 }145 if(ans==0)printf("?\n");146 else{147 if(t==1)printf("%s\n",temp2);148 else149 print(ans,sumlen);150 }151 152 }153 return 0;154 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。