POJ 3693 Maximum repetition substring(字尾陣列求最長重複子串)

畫船聽雨發表於2015-01-26

題目大意:和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;
}


相關文章