POJ 3693 Maximum repetition substring(後綴數組求最長重複子串)

題目大意:和spoj687類似,就是當長度相同是需要輸出一個最小的字典序的序列。

解體思路:這次需要枚舉所有的從i到d = i-L/i (d = i-L%i)的位置,然後記錄保證最大值的同時,求出來字典序最小的。

Maximum repetition substring
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7418   Accepted: 2217

Description

The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

Input

The input consists of multiple test cases. Each test case contains exactly one line, which
gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.

The last test case is followed by a line containing a '#'.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.

Sample Input

ccabababc
daabbccaa
#

Sample Output

Case 1: ababab
Case 2: aa
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <map>
#include <set>
#define eps 1e-9
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
#define mod 1000000007

#define Read() freopen("autocomplete.in","r",stdin)
#define Write() freopen("autocomplete.out","w",stdout)
#define Cin() ios::sync_with_stdio(false)

using namespace std;


inline int read()
{
    char ch;
    bool flag = false;
    int a = 0;
    while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-')));
    if(ch != '-')
    {
        a *= 10;
        a += ch - '0';
    }
    else
    {
        flag = true;
    }
    while(((ch = getchar()) >= '0') && (ch <= '9'))
    {
        a *= 10;
        a += ch - '0';
    }
    if(flag)
    {
        a = -a;
    }
    return a;
}
void write(int a)
{
    if(a < 0)
    {
        putchar('-');
        a = -a;
    }
    if(a >= 10)
    {
        write(a / 10);
    }
    putchar(a % 10 + '0');
}

const int maxn = 100050;

int wa[maxn], wb[maxn], wv[maxn], ws1[maxn];
int sa[maxn];

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;
    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 <<= 1, 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(swap(x, y), 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 *r, int *sa, int n)
{
    int i, j, k = 0;
    for(i = 1; i <= n; i++) rank[sa[i]] = i;
    for(int 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 dp[maxn][30];


void RMQ(int len)
{
    for(int i = 1; i <= len; i++)
        dp[i][0] = height[i];
    for(int j = 1; 1<<j <= maxn; j++)
    {
        for(int i = 1; i+(1<<j)-1 <= len; i++)
            dp[i][j] = min(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
    }
}
int lg[maxn];

int querry(int l, int r)
{
    int k = lg[r-l+1];
    return min(dp[l][k], dp[r-(1<<k)+1][k]);
}


void init()
{
    lg[0] = -1;
    for (int i = 1; i < maxn; ++i)
        lg[i] = lg[i>>1] + 1;
}
int seq[maxn];
char str[maxn];
void Del(int n, int Case)
{
    int Max = 0;
    string tmx, tmp;
    for(int i = 1; i <= n/2; i++)
    {
        for(int j = 0; i*j+i < n; j++)
        {
            int l = rank[i*j];
            int r = rank[i*j+i];
            if(l > r) swap(l, r);
            int x = querry(l+1, r);
            int y = 0;
            if(Max <= x/i + 1)
            {
                ///assign是string的一個賦值函數string.assign(const char *, int, int);
                tmp.assign(str, i*j, i*(x/i+1));
                if(x/i+1 > Max)
                {
                    Max = x/i+1;
                    tmx = tmp;
                }
                else
                {
                    int xn = tmx.size();
                    if(!xn || tmx > tmp)
                    tmx = tmp;
                }
            }

            int xp = i - x%i;
            if(xp && j)
            {
                for(int k = xp; k < i; k++)
                {
                    l = rank[i*j-k];
                    r = rank[i*j+i-k];
                    if(l > r) swap(l, r);
                    y = querry(l+1, r);
                    int yp = y/i+1;
                    if(yp < Max) continue;
                    tmp.assign(str, i*j-k, i*yp);
                    if(Max < yp)
                    {
                        tmx = tmp;
                        Max = yp;
                    }
                    else
                    {
                        int yn = tmx.size();
                        if(!yn || tmx > tmp)
                            tmx = tmp;
                    }
                }
            }
        }
    }
    printf("Case %d: ",Case);
    cout<<tmx<<endl;
}


int main()
{
    init();
    int Case = 1;
    while(scanf("%s", str) && str[0] != '#')
    {
        int n = strlen(str);
        for(int i = 0; i < n; i++) seq[i] = str[i]-'a'+1;
        seq[n] = 0;
        da(seq, sa, n+1, 27);
        calheight(seq, sa, n);
        RMQ(n);
        Del(n, Case++);
    }
    return 0;
}


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