zoukankan      html  css  js  c++  java
  • 2013 ACM/ICPC 长春网络赛E题

    题意:给出一个字符串,要从头、尾和中间找出三个完全相等的子串,这些串覆盖的区间互相不能有重叠部分。头、尾的串即为整个字符串的前缀和后缀。问这个相同的子串的最大长度是多少。

    分析:利用KMP算法中的next数组。next数组有一个性质,如果next[b]指向a。a<b。那么 以a作为结尾的原串前缀 是 以b作为结尾的原串前缀 的后缀。

    那么如果b是原串的最后一位,那么以b结尾的前缀就是原串,则a结尾的前缀与一个原串的后缀相等。

    我们既然找到了一个相等的前缀和后缀,只需要再判断中间是否有相同的子串即可。即判断是否存在next[c]==a,或者next[next[c]]==a,或者……

    如果没有我们就缩短前缀的长度,方法就是让a=next[next[b]],a=next[next[next[b]]],这样不断迭代。每次这样判断,直到找到一个中间存在相等串的为止。

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define MAX_SONG_LEN 1000005
    
    char song[MAX_SONG_LEN];
    int left_link[MAX_SONG_LEN];
    int song_len;
    
    void input()
    {
        scanf("%s", (song + 1));
        song_len = strlen(song + 1);
        song[0] = -1;
    }
    
    void kmp(char st[], int next[], int len)
    {
        next[1] = 0;
        next[0] = -1;
        for (int i = 2; i <= len; i++)
        {
            int temp = next[i - 1];
            while (temp >= 0 && st[i] != st[temp + 1])
                temp = next[temp];
            next[i] = temp + 1;
        }
    }
    
    bool reach(int l, int r)
    {
        while (r > l)
            r = left_link[r];
        return r == l;
    }
    
    int work()
    {
        int prefix_end = song_len;
        while (prefix_end > 0)
        {
            if (prefix_end > song_len / 2)
            {
                prefix_end = left_link[prefix_end];
                continue;
            }
            int theme_len = prefix_end;
            int suffix_begin = song_len - theme_len + 1;
            int mid_end = prefix_end;
            for (int i = prefix_end + 1; i < suffix_begin; i++)
                if (reach(prefix_end, i) && i - prefix_end >= theme_len)
                    return theme_len;
            prefix_end = left_link[prefix_end];
        }
        return 0;
    }
    
    int main()
    {
        int case_num;
        scanf("%d", &case_num);
        while (case_num--)
        {
            input();
            kmp(song, left_link, song_len);
            printf("%d
    ", work());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Day3-python基础3
    批量分发
    Day2-python基础2
    数据类型总结,and字符编码和文件处理
    集合与字符编码
    列表等及其部分讲解
    赋值符号和循环略解
    Python中常量,和基本数据类型,输入输出的方法,基本运算符。
    Python解释器了解,及部分变量
    计算机硬件,操作系统,编程语言
  • 原文地址:https://www.cnblogs.com/rainydays/p/3344439.html
Copyright © 2011-2022 走看看