[zoj][3395][Stammering Aliens]

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3971

二分答案mid,用height数组判断出现连续k次,记录出现的最大下标1,二分循环时,更新最大下标2,最后输出答案。

View Code
#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;



const int N = 40000+100;



int us[N], ua[N], ub[N], sa[N];



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 n, int m){

    int i, j, p, *x=ua, *y=ub, *t;

    for (i=0; i<m; i++) us[i]=0;

    for (i=0; i<n; i++) us[x[i]=r[i]]++;

    for (i=1; i<m; i++) us[i]+=us[i-1];

    for (i=n-1; i>=0; i--) sa[--us[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<m; i++) us[i]=0;

        for (i=0; i<n; i++) us[x[i]]++;

        for (i=1; i<m; i++) us[i]+=us[i-1];

        for (i=n-1; i>=0; i--) sa[--us[x[y[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++;

    }

}



int rank[N], height[N], arr[N];

void calheight(int *r, 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++);

}

char str[N];



int main(){

    //freopen("D:/a.txt", "r", stdin);

    int k, n, st, ed, mid, ans, p;

    while (~scanf("%d", &k) && k){

        n = 0;

        scanf("%s", str);

        if (k==1){printf("%d 0\n", strlen(str)); continue;}

        for (int i=0; str[i]; i++)

            arr[n++] = str[i];

        arr[n] = 0;

        da(arr, n+1, 128);

        calheight(arr, n);

        ans = 0, p = -1, st = 0,ed = n;

        while (st <= ed){

            int tp = 0, flag = 0, maxi = 0;

            mid = st + (ed - st) / 2;

            for (int i=1,cnt=1; i<=n; i++){

                if (height[i]>=mid) cnt++,tp = max(tp,sa[i]);

                else cnt=1, tp=sa[i];

                if (cnt >= k){

                    flag = 1; maxi = max(maxi, tp);

                }

            }

            if (flag) ans= mid, st = mid+1, p=maxi;

            else ed = mid-1;

        }

        if (ans>0)printf("%d %d\n", ans, p);

        else puts("none");

    }

    return 0;

}

你可能感兴趣的:(ZOJ)