zoukankan      html  css  js  c++  java
  • 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)是从起始位置输出字符直到遇到为止,合法,

      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]='';//这里由于自己没有加上这一句,结果wa了,因为www之前没有清空
    102                 printf("%s
    ",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("?
    ");
    146     else{
    147         if(t==1)printf("%s
    ",temp2);
    148         else
    149         print(ans,sumlen);
    150     }
    151 
    152     }
    153     return 0;
    154 }
    View Code
  • 相关阅读:
    一步一步教你在GridView中实现可收缩的面板
    收藏微软面试智力题 (附答案)
    WF4.0实战(一):文件审批流程
    WF4.0实战(六):控制WPF动画
    WF4.0实战(十一):邮件通知
    WF4.0实战(十):分布式酒店订房系统
    WF4.0实战(十六):模拟红绿灯
    WF4.0实战(五):实现一个直观易扩展的自动测试框架
    Beginning WF4读书笔记(一):创建一个简单的工作流
    DataGridView打印类
  • 原文地址:https://www.cnblogs.com/chujian123/p/3907932.html
Copyright © 2011-2022 走看看