zoukankan      html  css  js  c++  java
  • POJ

    传送门:POJ - 3294   (类似题目POJ - 3450)

    题意:给你n个字符串,求在不小于k/2个字符串中出现过的最长子串。

    题解:首先将n个字符串连起来,中间用不一样且没出现过的字符连起来(这个地方让我wa了好几发!!),然后二分字串的长度,将后缀分成若干组,判断每组的后缀是否在不小于k个的原串中出现过,数组sum记录每个最长字符串在原串中出现的位置sa[i]。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<queue>
      4 #include<iostream>
      5 #include<cmath>
      6 #include<cstring>
      7 using namespace std;
      8 
      9 const int maxn = 1000100;
     10 int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
     11 int rnk[maxn],height[maxn],sum[maxn];
     12 char s[maxn];
     13 int r[maxn],n,pos=0,len[110],vis[110],ans=0,L,be[maxn];
     14 
     15 //sa:字典序中排第i位的起始位置在str中第sa[i]  sa[1~n]为有效值
     16 
     17 //rnk:就是str第i个位置的后缀是在字典序排第几 rnk[0~n-1]为有效值
     18 
     19 //height:字典序排i和i-1的后缀的最长公共前缀  height[2~n]为有效值,第二个到最后一个
     20 
     21 int cmp(int *r,int a,int b,int k)
     22 {
     23     return r[a]==r[b]&&r[a+k]==r[b+k];
     24 }
     25 
     26 void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
     27 {
     28     int i,j,p,*x=wa,*y=wb,*t;
     29     for(i=0; i<m; i++)  wsf[i]=0;
     30     for(i=0; i<=n; i++)  wsf[x[i]=r[i]]++;
     31     for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
     32     for(i=n; i>=0; i--)  sa[--wsf[x[i]]]=i;
     33     p=1;
     34     j=1;
     35     for(; p<=n; j*=2,m=p){
     36         for(p=0,i=n+1-j; i<=n; i++)  y[p++]=i;
     37         for(i=0; i<=n; i++)  if(sa[i]>=j)  y[p++]=sa[i]-j;
     38         for(i=0; i<=n; i++)  wv[i]=x[y[i]];
     39         for(i=0; i<m; i++)  wsf[i]=0;
     40         for(i=0; i<=n; i++)  wsf[wv[i]]++;
     41         for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
     42         for(i=n; i>=0; i--)  sa[--wsf[wv[i]]]=y[i];
     43         swap(x,y);
     44         x[sa[0]]=0;
     45         for(p=1,i=1; i<=n; i++)
     46             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
     47     }
     48 }
     49 
     50 void getheight(int *r,int n)//n为添加0后的总长
     51 {
     52     int i,j,k=0;
     53     for(i=1; i<=n; i++)  rnk[sa[i]]=i;
     54     for(i=0; i<n; i++){
     55         if(k)
     56             k--;
     57         else
     58             k=0;
     59         j=sa[rnk[i]-1];
     60         while(r[i+k]==r[j+k])
     61             k++;
     62         height[rnk[i]]=k;
     63     }
     64 }
     65 
     66 bool check(int k)
     67 {
     68     int cnt=0,p=0;
     69     memset(vis,0,sizeof(vis));
     70     for(int i=1;i<=L;i++){
     71         if(height[i]>=k){
     72             if(!vis[be[sa[i]]]) cnt++;
     73             vis[be[sa[i]]]=1;
     74             if(!vis[be[sa[i-1]]]) cnt++;
     75             vis[be[sa[i-1]]]=1;
     76         }
     77         else{
     78             if(cnt>n/2) sum[p++]=sa[i-1];
     79             cnt=0;
     80             memset(vis,0,sizeof(vis));
     81         }
     82     }
     83     if(cnt>n/2) sum[p++]=sa[L];
     84     cnt=0;
     85     if(p) ans=p;
     86     if(p) return 1;
     87     return 0;
     88 }
     89 
     90 int main()
     91 {
     92     ios::sync_with_stdio(false);
     93     cin.tie(0);
     94     cout.tie(0);
     95     int t=0;
     96     while(cin>>n&&n){
     97         L=0;
     98         for(int i=1;i<=n;i++){
     99             cin>>s+L;
    100             int p=strlen(s+L);
    101             for(int j=0;j<p;j++){
    102                 r[j+L]=s[j+L]-'A'+1;
    103                 be[j+L]=i;
    104             }
    105             L+=p;
    106             len[i]=L;
    107             if(i!=n){
    108                 r[L]=100+i;
    109                 be[L]=i;
    110                 L++;
    111             }
    112         }
    113         r[L]=0;
    114         getsa(r,sa,L,300);
    115         getheight(r,L);
    116         int l=1,r=L;
    117         ans=0;
    118         while(l<=r){
    119             int mid=l+r>>1;
    120             if(check(mid)){
    121                 l=mid+1;
    122             }
    123             else r=mid-1;
    124         }
    125         if(t) cout<<endl;
    126         t=1;
    127         if(l==1) cout<<"?"<<endl;
    128         for(int i=0;i<ans;i++){
    129             for(int j=sum[i];j<sum[i]+l-1;j++){
    130                 cout<<s[j];
    131             }
    132             cout<<endl;
    133         }
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    HTML页面之间跳转传值
    Ajax之三种数据传输格式
    css选择器
    jQuery Validate
    正则表达式
    JSP的九大内置对象,七大动作指令,四个作用域,三个编译指令
    Zooeeper之paxos算法
    ZooKeeper之选举(fastleaderelection算法)
    ZooKeeper之ZAB协议
    ZooKeeper之三阶段提交(3PC)
  • 原文地址:https://www.cnblogs.com/lilibuxiangtle/p/12649853.html
Copyright © 2011-2022 走看看