zoukankan      html  css  js  c++  java
  • POJ 3693 Maximum repetition substring(最多重复次数的子串)

    Maximum repetition substring
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 10461   Accepted: 3234

    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

    题目链接:POJ 3693

    把所有可能构成的最多重复次数的子串所对应的循环节大小存下来,然后枚举$SA[i]$与循环节大小,如果刚好枚举到了这个$SA[i]$对应的就是这个循环节大小,那么就是最小的字典序解了,因为$SA[]$是按照字典序排的,当然要注意单个字符这种字符串,因此一开始要把长度定为1。

    另外这题数据非常弱,实际上枚举的时候需要加一些边界防止越界问题。可以试一下这些数据:

    kabhvlkba
    slgnaebbga
    lajnbabab
    kabkbakbvkab
    akbakabka
    akjbakjbajkba
    akjbakbaiajklbna
    kljdfnbisn
    akbvkab

    答案应该是

    a

    b

    abab

    a

    a

    akjbakjb

    a

    b

    a

    代码:

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <bitset>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define fin(name) freopen(name,"r",stdin)
    #define fout(name) freopen(name,"w",stdout)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 100010;
    int wa[N], wb[N], cnt[N], sa[N];
    int ran[N], height[N];
    char s[N];
    int pos[N];
    
    inline int cmp(int r[], int a, int b, int d)
    {
        return r[a] == r[b] && r[a + d] == r[b + d];
    }
    void DA(int n, int m)
    {
        int i;
        int *x = wa, *y = wb;
        for (i = 0; i < m; ++i)
            cnt[i] = 0;
        for (i = 0; i < n; ++i)
            ++cnt[x[i] = s[i]];
        for (i = 1; i < m; ++i)
            cnt[i] += cnt[i - 1];
        for (i = n - 1; i >= 0; --i)
            sa[--cnt[x[i]]] = i;
        for (int k = 1; k <= n; k <<= 1)
        {
            int p = 0;
            for (i = n - k; i < n; ++i)
                y[p++] = i;
            for (i = 0; i < n; ++i)
                if (sa[i] >= k)
                    y[p++] = sa[i] - k;
            for (i = 0; i < m; ++i)
                cnt[i] = 0;
            for (i = 0; i < n; ++i)
                ++cnt[x[y[i]]];
            for (i = 1; i < m; ++i)
                cnt[i] += cnt[i - 1];
            for (i = n - 1; i >= 0; --i)
                sa[--cnt[x[y[i]]]] = y[i];
            swap(x, y);
            x[sa[0]] = 0;
            p = 1;
            for (i = 1; i < n; ++i)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], k) ? p - 1 : p++;
            m = p;
            if (m >= n)
                break;
        }
    }
    void gethgt(int n)
    {
        int i, k = 0;
        for (i = 1; i <= n; ++i)
            ran[sa[i]] = i;
        for (i = 0; i < n; ++i)
        {
            if (k)
                --k;
            int j = sa[ran[i] - 1];
            while (s[j + k] == s[i + k])
                ++k;
            height[ran[i]] = k;
        }
    }
    namespace SG
    {
        int dp[N][17];
        void init(int l, int r)
        {
            int i, j;
            for (i = l; i <= r; ++i)
                dp[i][0] = height[i];
            for (j = 1; l + (1 << j) - 1 <= r; ++j)
            {
                for (i = l; i + (1 << j) - 1 <= r; ++i)
                    dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
            }
        }
        int ask(int l, int r)
        {
            int len = r - l + 1;
            int k = 0;
            while (1 << (k + 1) <= len)
                ++k;
            return min(dp[l][k], dp[r - (1 << k) + 1][k]);
        }
        int LCP(int l, int r, int len)
        {
            l = ran[l], r = ran[r];
            if (l > r)
                swap(l, r);
            if (l == r)
                return len - sa[l];
            return ask(l + 1, r);
        }
    }
    int main(void)
    {
        int T = 0, len, i, j;
        while (~scanf("%s", s) && s[0] != '#')
        {
            len = strlen(s);
            DA(len + 1, 130);
            gethgt(len);
            SG::init(1, len);
            int ans = 1;
            int sz = 0;
            for (int L = 1; L < len; ++L)
            {
                for (i = 0; i + L < len; i += L)
                {
                    int lcp = SG::LCP(i, i + L, len);
                    int cnt = lcp / L + 1;
                    int j = i - (L - lcp % L);
                    if (j >= 0 && lcp % L != 0 && SG::LCP(j , j + L, len) / L + 1 > cnt)
                        ++cnt;
                    if (cnt > ans)
                    {
                        ans = cnt;
                        sz = 0;
                        pos[sz++] = L;
                    }
                    else if (cnt == ans)
                        pos[sz++] = L;
                }
            }
            int length = 1;
            int st = 0;
            int flag = 0;
            for (i = 1; i <= len && !flag; ++i)
            {
                for (j = 0; j < sz; ++j)
                {
                    int unit = pos[j];
                    if (sa[i] + unit < len && SG::LCP(sa[i], sa[i] + unit, len) >= (ans - 1) * unit)
                    {
                        length = ans * unit;
                        st = sa[i];
                        flag = 1;
                        break;
                    }
                }
            }
            printf("Case %d: ", ++T);
            for (i = st; i < st + length; ++i)
                putchar(s[i]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    Android内存优化杂谈
    ANDROID内存优化(大汇总——全)
    ANDROID内存优化(大汇总——中)
    ANDROID内存优化(大汇总——上)
    Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)
    Java反射学习总结五(Annotation(注解)-基础篇)
    Java反射学习总结四(动态代理使用实例和内部原理解析)
    Java反射学习总结三(静态代理)
    Java反射学习总结二(用反射调用对象的私有属性和方法)
    Java反射学习总结一(基础篇)
  • 原文地址:https://www.cnblogs.com/Blackops/p/7520818.html
Copyright © 2011-2022 走看看