life forms poj3294(寫了很久才寫過)

後綴數組還是不熟

首先總數組的最後一個r[n]必須是0

其次設置的最大值一定要比r中最大值大

再其次 多個字符串拼接時 拼接的字符一定要不相同

最後 題目給的n上限100莫名坑爹 

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 4000000+1000;
int t1[maxn],t2[maxn],c[maxn];
int n;
bool cmp(int *r, int a, int b, int l){
    return r[a]==r[b]&&r[a+l]==r[b+l];
}
int len = 0;

void da(int str[], int sa[], int rank[], int height[], int n, int m){
    n++;
    int i, j, p, *x = t1, *y = t2;
    for(int i = 0;i<m;++i)c[i] = 0;
    for(int i = 0;i<n;++i)c[x[i]=str[i]]++;
    for(int i = 1;i<m;++i)c[i]+=c[i-1];
    for(int i =n-1;i>=0;i--)sa[--c[x[i]]] = i;
    for(j = 1;j<=n;j<<=1){
        p = 0;
        for(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)c[i] = 0;
        for(i = 0;i<n;++i)c[x[y[i]]]++;
        for(i = 1;i<m;++i)c[i]+=c[i-1];
        for(i = n-1;i>=0;--i)sa[--c[x[y[i]]]]  =y[i];
        swap(x,y);
        p = 1;
        x[sa[0]] = 0;
        for(i = 1;i<n;++i)
            x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        if(p>=n)break;
        m = p;

    }
    int k = 0;
    n--;
    for(i = 0;i<=n;++i){
        rank[sa[i]] = i;
    }
    for(i = 0;i<n;++i){
        if(k)k--;
        j = sa[rank[i]-1];
        while(str[i+k]==str[j+k]){
            k++;
        }
        height[rank[i]] = k;
    }
}

int Rank[maxn],height[maxn];
char str[maxn];
int r[maxn],sa[maxn];
int s[maxn];
int id[maxn];
char ss[2000][2000];
int now_ans[10000];
int ans[10000];
int vis[10000];
int cnt = 0;
int num = 0;

int check(int x,int k){
    cnt = 0;
    num = 0;
    for(int i = 1;i<=300;++i)vis[i] = 0;
//    for(int i = 2;i<=n;++i){ n給的100 但是初始化100個肯定錯 不知道原因 這樣寫1000+ms
//        if(height[i]<x){
//            if(cnt>k){
//                ans[num++] = sa[i-1];
//            }
//            cnt = 0;
//            for(int i = 1;i<=300;++i)vis[i] = 0;
//        }
//        else{
//            if(!vis[id[sa[i]]])vis[id[sa[i]]]=1,cnt++;
//            if(!vis[id[sa[i-1]]])vis[id[sa[i-1]]]=1,cnt++;
//        }
//    }
    int top = -1;//這樣寫300+ms
    int sta[400];
    for(int i = 2;i<=n;++i){
        if(height[i]<x){
            if(cnt>k){
                ans[num++] = sa[i-1];

            }
            cnt = 0;
            while(top!=-1){
                vis[sta[top--]]= 0;
            }
        }
        else{
            if(!vis[id[sa[i]]])vis[id[sa[i]]]=1,cnt++,sta[++top] = id[sa[i]];
            if(!vis[id[sa[i-1]]])vis[id[sa[i-1]]]=1,cnt++,sta[++top] = id[sa[i-1]];
        }
    }
    return num;
}
int main(){
    int m;
    int cas = 0;
    while(~scanf("%d",&m)&&m){
        n = 0;
        int maxs = 130;
        int l = 1,right = 0x3f3f3f3f;
        for(int i = 1;i<=m;++i){
            scanf("%s",ss[i]);
            int len = strlen(ss[i]);
            right = min(right,len);
            for(int j = 0;j<len;++j){
                r[++n] = (int)ss[i][j];
                id[n] = i;
            }
            r[++n] = ++maxs;
        }
        r[n] = 0;
        da(r,sa,Rank,height,n,maxs+1);
//        for(int i = 1;i<=n;++i){
//            cout<<height[i]<<" ";
//        }
//        cout<<endl;
//        for(int i = 1;i<=n;++i){
//            cout<<id[i]<<" ";
//        }
//        cout<<endl;
        int now_num = 0;
        int length = 0;
//        cout<<right<<endl;
        while(l<=right){
            int mid = (l+right)>>1;
            //cout<<mid<<endl;
            if(check(mid,m/2)){
                now_num = num;
                length = mid;

                for(int i = 0;i<num;++i){
                    now_ans[i] = ans[i];
                }
                l = mid+1;
            }
            else right = mid - 1;
            // cout<<mid<<" "<<num<<endl;
        }
        // cout<<now_num<<" "<<length<<endl;
        if(cas)cout<<endl;
        cas++;
        if(now_num){
            for(int i = 0;i<now_num;++i){
                for(int j = now_ans[i];j<now_ans[i]+length;++j){
                    //cout<<"j"<<j<<endl;
                    printf("%c",r[j]);
                }
                printf("\n");
            }
        }
        else{
            printf("?\n");
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章