zoukankan      html  css  js  c++  java
  • Repeats SPOJ

    A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string

    s = abaabaabaaba

    is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.

    Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string

    u = babbabaabaabaabab

    contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.

    Input
    In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.

    Output
    For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.

    Example
    Input:
    1
    17
    b
    a
    b
    b
    a
    b
    a
    a
    b
    a
    a
    b
    a
    a
    b
    a
    b

    Output:
    4

    思路:根据罗穗骞论文,若循环节的长度为len且循环次数大于1, 则1, 1 + len, 1 + 2 * len, 1 + 3 * len......中某相邻的两个字符必然是所求字符串中的两个字符,然后我们来看suffix[i] 和 suffix[i + len] 的最长公共前缀 LCP(i, i + len) = k, 定义 le = i, ri = i + len + k - 1, 可以发现,k 类似于KMP中的 next[n] (不懂得可以去看一下KMP求最小循环节), 所以 le ~ ri 的循环节个数至少为 k / len + 1, 然后就是向左匹配操作了。

    关于求任意的 LCP(i, j) 的 ,其实就是求 min(Height[(rank[i] + 1) ~ rank[j]), 这里默认rank[i] < rank[j]。

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <string>
    #include <math.h>
    #include <string.h>
    #include <map>
    #include <iostream>
    using namespace std;
    const int maxn = 5e5 + 50;
    const int mod = 20090717;
    int INF = 1e9;
    typedef pair<int, int> pii;
    #define fi first
    #define se second
    int Sa[maxn], Height[maxn], Tax[maxn], Rank[maxn], tp[maxn], a[maxn], n, m;
    char str[maxn];
    
    void Rsort(){
        for(int i = 0; i <= m; i++) Tax[i] = 0;
        for(int i = 1; i <= n; i++) Tax[Rank[tp[i]]]++;
        for(int i = 1; i <= m; i++) Tax[i] += Tax[i - 1];
        for(int i = n; i >= 1; i--) Sa[Tax[Rank[tp[i]]]--] = tp[i];
    }
    
    int cmp(int *f, int x, int y, int w){
        if(x + w > n || y + w > n) return 0; // 注意防止越界,多组输入的时候这条必须有
        return f[x] == f[y] && f[x + w] == f[y + w];
    }
    
    void Suffix(){
        for(int i = 1; i <= n; i++) Rank[i] = a[i], tp[i] = i;
        m = 200, Rsort();
        for(int w = 1, p = 1, i; p < n; w += w, m = p){
            for(p = 0, i = n - w + 1; i <= n; i++) tp[++p] = i;
            for(i = 1; i <= n; i++) if(Sa[i] > w) tp[++p] = Sa[i] - w;
            Rsort(), swap(Rank, tp), Rank[Sa[1]] = p = 1;
            for(int i = 2; i <= n; i++)  Rank[Sa[i]] = cmp(tp, Sa[i], Sa[i - 1], w) ? p : ++p;
        }
        int j, k = 0;
        for(int i = 1; i <= n; Height[Rank[i++]] = k){
            for(k = k ? k - 1 : k, j = Sa[Rank[i] - 1]; a[i + k] == a[j + k]; ++k);
        }
    }
    
    int dpmi[maxn][60];
    void RMQ(){
        for(int i = 1; i <= n; i++){
            dpmi[i][0] = Height[i];
        }
        for(int j = 1; (1 << j) <= n; j++){
            for(int i = 1; i + (1 << j) - 1 <= n; i++){
                dpmi[i][j] = min(dpmi[i][j - 1], dpmi[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
    
    int QueryMin(int l, int r){
        int k = log2(r - l + 1);
        return min(dpmi[l][k], dpmi[r - (1 << k) + 1][k]);
    } 
    
    int QueryLcp(int i, int j){
        i = Rank[i], j = Rank[j];
        if(i > j) swap(i, j);
        i++;
        return QueryMin(i, j);
    }
    int main(int arg, char const *argv[])
    {
        int t;
        scanf("%d", &t);
        while(t--){
            scanf("%d", &n);
            for(int i = 1; i <= n; i++){
                char ch;
                scanf(" %c", &ch);
                a[i] = ch;
            }
            Suffix();
            RMQ();
            int ans = 0;
            for(int len = 1; len <= n; len++){
                for(int i = 1; i + len <= n; i += len){
                    int res1 = QueryLcp(i, i + len);
                    int cnt = res1 / len + 1;
                    int j = i - (len - res1 % len);
                    if(j > 0){ 
                        int res2 = QueryLcp(j, j + len);
                        if(res2 / len + 1 > cnt) cnt++;
                        ans = max(ans, cnt);
                    }
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    Redis学习笔记
    RedisTemplate操作命令
    RedisTemplate操作命令
    RedisTemplate操作命令
    RedisTemplate操作命令
    将chrome储存的密码转为MarkDown表格
    使用redisson做redis分布式锁
    RocketMQ 整合SpringBoot发送事务消息
    关于java读写锁的测试
    java8 stream记录
  • 原文地址:https://www.cnblogs.com/PCCCCC/p/13281994.html
Copyright © 2011-2022 走看看