poj 3693 (后缀数组)

/*
 * =====================================================================================
 *
 *       Filename:  c.cpp
 *        Version:  1.0
 *        Created:  08/20/2013 03:06:41 PM
 *       Revision:  none
 *       Compiler:  GNU C++
 *
 *      Just like you,wait you forever~~
 *
 * =====================================================================================
 */
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define PB              push_back
#define SIZE(x)         (int)x.size()
#define clr(x,y)        memset(x,y,sizeof(x))
#define MP(x,y)         make_pair(x,y)
#define RS(n)           scanf ("%s", n)
#define ALL(t)          (t).begin(),(t).end()
#define FOR(i,n,m)      for (int i = n; i <= m; i ++)
#define ROF(i,n,m)      for (int i = n; i >= m; i --)
#define IT              iterator
#define FF              first
#define SS              second

typedef long long               ll;
typedef unsigned int            uint;
typedef unsigned long long      ull;
typedef vector<int>             vint;
typedef vector<string>          vstring;
typedef pair<int, int>          PII;

void RI (int& x){
        x = 0;
        char c = getchar ();
        while (c == ' '||c == '\n')    c = getchar ();
        bool flag = 1;
        if (c == '-'){
                flag = 0;
                c = getchar ();
        }
        while (c >= '0' && c <= '9'){
                x = x * 10 + c - '0';
                c = getchar ();
        }
        if (!flag)    x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}

/**************************************END define***************************************/

const ll mod = 1e9+7;
const ll LINF = 1e18;
const int INF = 1e9;
const double EPS = 1e-8;

const int maxn = 100005;

int sa[maxn],r[maxn];
int cmp(int *r,int a,int b,int l)//
{
        return r[a]==r[b]&&r[a+l]==r[b+l];
}
int wa[maxn],wb[maxn],wv[maxn],ws1[maxn];
void makesa (int n,int m)//
{
        r[n++]=0;
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0; i<m; i++)ws1[i]=0;
        for(i=0; i<n; i++)ws1[x[i]=r[i]]++;
        for(i=1; i<m; i++)ws1[i]+=ws1[i-1];
        for(i=n-1; i>=0; i--)sa[--ws1[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++) ws1[i]=0;
                for(i=0; i<n; i++) ws1[wv[i]]++;
                for(i=1; i<m; i++) ws1[i]+=ws1[i-1];
                for(i=n-1; i>=0; i--) sa[--ws1[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++;
        }
}
int rank[maxn],height[maxn];
void calheight(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++);
}

int dp[20][100005];

void rmqinit (int n){
        FOR (i, 1, n){
                dp[0][i] = height[i];
        }
        int len = floor (log2 (100005));
        FOR (j, 1, len){
                for (int i = 1; i + (1 << j) - 1 <= maxn; i ++){
                        dp[j][i] = min (dp[j-1][i], dp[j-1][i+(1<<(j-1))]);
                }
        }
}

int lcp(int i,int j)
{
        int m = min (rank[i], rank[j])+1;
        int n = max (rank[i], rank[j]);
        int len = floor (log(n-m+1)/log(2));
        return min (dp[len][m], dp[len][n-(1<<len)+1]);
}

char s[maxn];
int n;

int main (){
        int cass = 1;
        while (gets (s), s[0] != '#'){
                int len = strlen (s);
                FOR (i, 0, len-1){
                        r[i] = s[i];
                }
                makesa (len, 'z'+1);
                calheight (len);
                rmqinit (len);
                vint vec;
                int cnt = 0;
                FOR (i, 1, len){
                        for (int j = 0; j+i <= len; j += i){
                                int cp = lcp (j, j+i); 
                                int l = cp/i + 1;
                                int t = j - (i-cp%i);
                                if (t >= 0)     l = max (l, lcp (t, t+i)/i+1);
                                if (l > cnt){
                                        cnt = l;
                                        vec.clear ();
                                        vec.PB (i);
                                }else if (l == cnt){
                                        if (i != *(vec.rbegin ())){
                                                vec.PB (i);
                                        }
                                }
                        }
                }
                //cout << cnt << endl;
                int flag = 1, pos, tl;
                FOR (i, 1, len){
                        if (!flag)      break;
                        FOR (j, 0, SIZE (vec)-1){
                                int num = vec[j];
                                int p = sa[i];
                                if (p+num <= len){
                                        int cp = lcp (p, p+num);
                                        int l = cp/num + 1;
                                        if (l == cnt){
                                                pos = sa[i];
                                                tl = vec[j];
                                                flag = 0;
                                                break;
                                        }
                                }
                        }
                }
                printf ("Case %d: ", cass ++);
                FOR (i, pos, pos + tl*cnt - 1){
                        putchar (s[i]);
                }
                putchar ('\n');
        }
}

你可能感兴趣的:(poj 3693 (后缀数组))