zoukankan      html  css  js  c++  java
  • poj3294 后缀数组

    后缀数组多个字符串问题。 

    先求出height[]数组,然后二分求最大的长度。

    但是条件需要改变。如果出现次数大于一般那就满足。然后就要解决如何判断那一段属于其中一个字符串。

    所以先处理出长度。并且不断标记,如果在长度其中,将那个长度标记。那就不会出现自己与自己的相同情况了。

    RE了很多次,字符串输入的时候同时存入整数,防止过大可能使字符串出现问题。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<string>
    #include<map>
    #define LL long long
    using namespace std;
    #define maxn 1110000
    int max(int x,int y)
    {return x>y?x:y;}
    int min(int x,int y)
    {return x<y?x:y;}
    int wa[maxn],wb[maxn],wv[maxn],WS[maxn];
    int vex[maxn],size,vis[120],pre[maxn],cou;//vex存每一段的长度 size表示个数 pre存满足条件的开始位置 cou存满足的个数
    int cmp(int *r,int a,int b,int l)
    {return r[a]==r[b]&&r[a+l]==r[b+l];}
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++) WS[i]=0;
        for(i=0;i<n;i++) WS[x[i]=r[i]]++;
        for(i=1;i<m;i++) WS[i]+=WS[i-1];
        for(i=n-1;i>=0;i--) sa[--WS[x[i]]]=i;
        for(j=1,p=1;p<n;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<n;i++) wv[i]=x[y[i]];
            for(i=0;i<m;i++) WS[i]=0;
            for(i=0;i<n;i++) WS[wv[i]]++;
            for(i=1;i<m;i++) WS[i]+=WS[i-1];
            for(i=n-1;i>=0;i--) sa[--WS[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
        return;
    }
    int Rank[maxn],height[maxn];
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) Rank[sa[i]]=i;
        for(i=0;i<n;height[Rank[i++]]=k)
            for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
        return;
    }
    int r[maxn],sa[maxn];
    int ok(int x,int n,int k)
    {
        cou=0;
        int i,j,ret=0;
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++)
        {
            if(height[i]>=x)
            {
                for(j=1;j<size;j++)
                {
                    if(sa[i]>vex[j-1]&&sa[i]<vex[j])//由于自己添加的并不会相同 所以只要满足在中间位置就可以
                    {
                        if(!vis[j])//如果满足就标记掉那个位置
                        {
                            vis[j]=1;
                            ret++;
                        }
                    }
                    if(sa[i-1]>vex[j-1]&&sa[i-1]<vex[j])
                    {
                        if(!vis[j])
                        {
                            vis[j]=1;
                            ret++;
                        }
                    }
                }
            }
            else
            {
                if(ret>k)
                {
                    pre[cou++]=sa[i-1];
    
                }
                ret=0;
                memset(vis,0,sizeof(vis));
            }
        }
        if(ret>k)
        {
            pre[cou++]=sa[n];
        }
        if(cou>0)//表面有满足条件的
            return 1;
        return 0;
    }
    char s[maxn],c[maxn];
    int main()
    {
        int i,n,ff=0,fl;
        while(cin>>n)
        {
            if(!n)break;
            size=1;
            int len=0;
            int num=123;
            for(i=0;i<n;i++)
            {
                scanf("%s",c);
                int fl=strlen(c);
                for(int p=0;p<fl;p++)
                {
                    r[len]=c[p];//修改了此处 过了 之前是先存在s[]中 但是会出现问题 因为100多可能字符有问题
                    s[len++]=c[p];
                }
                vex[size++]=len;
                r[len]=num;
                s[len++]=num++;
            }
            len--;
            int j=len;
            r[j]=0;
            da(r,sa,j+1,250);
            calheight(r,sa,j);
            int left,right,mid,ans=-1;
            left=1,right=j,cou=0;
            while(left<=right)
            {
                mid=(left+right)/2;
                if(ok(mid,j,n/2))
                {
                    fl=cou;
                    ans=mid;
                    left=mid+1;
                }
                else right=mid-1;
            }
            /*for(i=1;i<=j;i++)
            printf("%d ",height[i]);
            printf("
    ");*/
            if(ff)
                printf("
    ");
            else ff=1;
            if(ans<=1)
            {
                printf("?
    ");
                continue;
            }
            //printf("%d
    ",ans);
            for(i=0;i<fl;i++)
            {
                for(j=0;j<ans;j++)
                {
                    printf("%c",s[pre[i]+j]);
                }
                printf("
    ");
            }
        }
    }
    /*
    5
    abcdef
    bcdea
    hzbcde
    bcdyz
    acxq
    */
  • 相关阅读:
    windows下安装部署RocketMQ
    Windows安装RabbitMQ
    HttpClient工具类
    Docker部署Spring Boot项目
    在Docker中安装Redis以及主从环境搭建
    df命令得到一个诡异的现象
    一个“稍后再读”的软件 POCKET
    也是关于 Stay Hungry. Stay Foolish.
    改用thebrain做思维导图
    文件系统只读,一个没有解决的问题(续)
  • 原文地址:https://www.cnblogs.com/sweat123/p/4799266.html
Copyright © 2011-2022 走看看