POJ 3693 Maximum repetition substring (后缀数组)

题目大意:

求出字典序最小,重复次数最多,的子串。

思路分析:

RMQ + height 数组可以求出任意两个后缀的lcp

我们枚举答案字符串的重复的长度。

如果这个字符串的长度为 l ,而且这个字符串出现过两次或两次以上

那么你会发现在原串中  str[0] str[l] str[2*l] ....肯定有相邻的两个被包含在重复的串中。

我们求出这两个相邻的后缀的lcp

我们上面仅仅说的是被包含在重复的串中,但并不一定就是以 str[0], str[l],str[2*l]....为起点的。

那我们就要往前去寻找这个起点。

也不是往前枚举,可以发现只要往前移动  l-lcp%l 个位置。

比如。

xbcabcab

当 l = 3 的时候

你找到了

ab

abcab

发现 lcp = 2,然后往前减去一个 l-lcp%l ,结果cab和cabcab的lcp 变成了3

也就是说往前寻找可以再补齐一个周期。

再讨论字典序最小的问题。

在sa中找到的第一个,满足最长的重复次数和长度的也就是字典序最小的了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 100005
using namespace std;

char str[maxn];
int sa[maxn],t1[maxn],t2[maxn],c[maxn],n;
void suffix(int m)
{
    int *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(int k=1; k<=n; k<<=1)
    {
        int p=0;
        for(int i=n-k; i<n; i++)y[p++]=i;
        for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
        for(int i=0; i<m; i++)c[i]=0;
        for(int i=0; i<n; i++)c[x[y[i]]]++;
        for(int i=0; i<m; i++)c[i]+=c[i-1];
        for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(int i=1; i<n; i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)break;
        m=p;
    }
}
int rank[maxn],height[maxn];
void getheight()
{
    int k=0;
    for(int i=0; i<n; i++)rank[sa[i]]=i;
    for(int i=0; i<n; i++)
    {
        if(k)k--;
        if(!rank[i])continue;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}

int f[maxn][30];

void RMQINIT()
{
    for(int i=0;i<n;i++)
    f[i][0]=height[i];

    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}

int RMQ(int l,int r)
{
    if(l>r)swap(l,r);
    l++;
    int k=floor(log(r-l+1.0)/log(2.0));
    return min(f[l][k],f[r+1-(1<<k)][k]);
}
int ans[maxn];
int main()
{
    int cas=1;
    while(scanf("%s",str)!=EOF && str[0]!='#')
    {
        n=strlen(str);
        str[n]=0;
        n++;
        suffix(128);
        getheight();
        RMQINIT();
        int Max=0;
        int top=0;
        for(int l=1;l<n;l++)
        {
            for(int i=l;i<n;i+=l)
            {
                int lcp=RMQ(rank[i-l],rank[i]);
                int repeat = lcp/l+1;

                int st = i-(l-lcp%l);

                if(st>=l && lcp%l)
                {
                    if(RMQ(rank[st-l],rank[st])>=lcp)
                    repeat++;
                }

                if(repeat>Max)
                {
                    Max=repeat;
                    top=0;
                    ans[top++]=l;
                }
                else if(repeat==Max)ans[top++]=l;
            }
        }
        int len=-1,st;
        for(int i=1;i<n && len==-1;i++)
        for(int j=0;j<top;j++)
        {
            if(RMQ(rank[sa[i]],rank[sa[i]+ans[j]])>=(Max-1)*ans[j])
            {
                len=ans[j];
                st=sa[i];
                break;
            }
        }
        printf("Case %d: ",cas++);
        for(int i=st;i<st+len*Max;i++)
        printf("%c",str[i]);
        puts("");
    }
    return 0;
}

POJ 3693 Maximum repetition substring (后缀数组),布布扣,bubuko.com

时间: 2024-10-12 16:21:15

POJ 3693 Maximum repetition substring (后缀数组)的相关文章

poj 3693 Maximum repetition substring(后缀数组)

题目链接:poj 3693 Maximum repetition substring 题目大意:求一个字符串中循环子串次数最多的子串. 解题思路:对字符串构建后缀数组,然后枚举循环长度,分区间确定.对于一个长度l,每次求出i和i+l的LCP,那么以i为起点,循环子串长度为l的子串的循环次数为LCP/l+1,然后再考虑一下从i-l+1~i之间有没有存在增长的可能性. #include <cstdio> #include <cstring> #include <vector>

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 numb

POJ - 3693 Maximum repetition substring(后缀数组求重复次数最多的连续重复子串)

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

POJ 3693 Maximum repetition substring ——后缀数组

重复次数最多的字串,我们可以枚举循环节的长度. 然后正反两次LCP,然后发现如果长度%L有剩余的情况时,答案是在一个区间内的. 所以需要找到区间内最小的rk值. 两个后缀数组,四个ST表,$\Theta(n\log n)$ 就可以解决了 空间卡死了,瞎晶胞卡过去了. #include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #incl

POJ - 3693 Maximum repetition substring 后缀数组+RMQ

http://poj.org/problem?id=3693 整体思路就是枚举长度L,看长度为L的字符串在s中连续出现了几次. 既然长度为L的串是重复出现的,那么s[0]-s[L]-s[2*L]-中相邻的两个一定出现在重复的L串中.(并不一定在首尾位置,也可能出现在中间). 那么我们求i*L和(i+1)*L的LCP,假设答案为M,那么答案应该是M/L+1(加一是因为i*L~(i+1)*L也是答案). 但是这个答案不一定是最优,举一个下面的例子. 此时M/L+1是3,而正确答案是4.为什么呢?是因

POJ 3693 Maximum repetition substring(后缀数组神题)

POJ 3693 Maximum repetition substring 题目链接 题意:给定一个字符串,求出其子串中,重复次数最多的串,如果有相同的,输出字典序最小的 思路:枚举长度l,把字符串按l分段,这样对于长度为l的字符串,肯定会包含一个分段位置,这样一来就可以在每个分段位置,往后做一次lcp,求出最大匹配长度,然后如果匹配长度有剩余,看剩余多少,就往前多少位置再做一次lcp,如果匹配出来长度更长,匹配次数就加1,这样就可以枚举过程中保存下答案了 这样问题还有字典序的问题,这个完全可以

POJ 3693 Maximum repetition substring (寻找重复次数最多的连续子串)

Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9083   Accepted: 2782 Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same conse

poj3693 Maximum repetition substring 后缀数组

http://poj.org/problem?id=3693 Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7241   Accepted: 2162 Description The repetition number of a string is defined as the maximum number R such that the string can b

POJ 3693 Maximum repetition substring(后缀数组+RMQ)

Maximum repetition substring 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&quo