zoukankan      html  css  js  c++  java
  • poj3294

    题解:

    后缀数组

    把所有的字符串用不同的分隔符连接起来

    然后求height,最后二分求长度为mid的子串是否有满足条件的

    记录满足条件的所有子串的首位置

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>  
    typedef long long LL;  
    using namespace std;  
    const int N=200000+10;  
    int *rank,r[N],sa[N],height[N],size,wa[N],wb[N],wm[N],len[110],pos[N],mark[110];  
    char s[N];  
    int cmp(int *r,int a,int b,int l)
    {  
        return r[a]==r[b]&&r[a+l]==r[b+l];  
    } 
    void makesa(int *r,int *sa,int n,int m){  
        int *x=wa,*y=wb;  
        for (int i=0;i<m;i++)wm[i]=0;  
        for (int i=0;i<n;i++)wm[x[i]=r[i]]++;  
        for (int i=1;i<m;i++)wm[i]+=wm[i-1];  
        for (int i=n-1;i>=0;i--)sa[--wm[x[i]]]=i;  
        for (int i=0,j=1,p=0;p<n;j=j*2,m=p)
         {  
            for (p=0,i=n-j;i<n;i++)y[p++]=i;  
            for (i=0;i<n;i++)
             if (sa[i]>=j)y[p++]=sa[i]-j;  
            for (i=0;i<m;i++)wm[i]=0;  
            for (i=0;i<n;i++)wm[x[y[i]]]++;  
            for (i=1;i<m;i++)wm[i]+=wm[i-1];  
            for (i=n-1;i>=0;i--)sa[--wm[x[y[i]]]]=y[i];  
            for (t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++)  
             x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;  
         }  
        rank=x;  
    }  
      
    void calheight(int *r,int *sa,int n)
    {  
        for (int i=0,j=0,k=0;i<n;height[rank[i++]]=k)
         for (k?--k:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);  
    }  
    int check(int mid,int n,int k)
    {  
        memset(mark,false,sizeof mark);  
        int num=0,ans=0;  
        for (int i=1;i<=n;i++)
         {  
             if (height[i]>=mid)
             {  
                for (int j=1;j<=size;j++)
                 {   
                    if (sa[i]>len[j-1]&&sa[i]<len[j])ans+=(mark[j]?0:1),mark[j]=1;  
                    if (sa[i-1]>len[j-1]&&sa[i-1]<len[j])ans+=(mark[j]?0:1),mark[j]=1;  
                 }  
             }
            else
             {  
                if (ans>k/2)pos[++num]=sa[i-1];   
                ans=0;  
                memset(mark,false,sizeof mark);  
             }  
         }  
        if (ans>k/2)pos[++num]=sa[n];  
        if (num){pos[0]=num;return 1;}   
        return 0;  
    }  
    int main()
    {  
        int k,n,num=0;  
        len[0]=-1;   
        while(scanf("%d",&k),k)
         {  
            pos[0]=size=n=0;   
            for(int i=0;i<k;i++)
             {  
                scanf("%s",s+n);  
                for(;s[n]!='';n++)r[n]=s[n];  
                r[len[++size]=n++]=300+i;   
             }  
            r[n-1]=0;  
            makesa(r,sa,n,400);  
            calheight(r,sa,n-1);  
            int L=1,R=n;  
            while (L<=R)
             {  
                int mid=L+R>>1;  
                if(check(mid,n,k))L=mid+1;  
                else R=mid-1;  
             }  
            if (num++)puts("");  
            if (L-1==0)puts("?");  
            else
             {  
                for (int i=1;i<=pos[0];i++)
                 {  
                    for (int j=pos[i];j<pos[i]+L-1;j++)printf("%c",s[j]);  
                    puts("");  
                 }  
             }  
         }  
        return 0;  
    }  
  • 相关阅读:
    mariadb配置双主多从
    mq系列rabbitmq-02集群+高可用配置
    mq系列rabbitmq-01简介,安装,api操作
    持续集成框架jenkins介绍02-持久集成git仓库+maven项目
    git仓库相关知识03-搭建远程仓库服务器
    RecyclerView瀑布流优化方案探讨
    Android实际开发bug大总结
    Android打造万能自定义阴影控件
    PagerAdapter深度解析和实践优化
    Java博客大汇总
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8523824.html
Copyright © 2011-2022 走看看