zoukankan      html  css  js  c++  java
  • [日常训练]article

    Description

    Y今天来写作文啦!
    Y非常善于堆砌辞藻。在洋洋洒洒写了一长篇之后,小Y发现作文中很多段落都似曾相识。小Y认为,如果一段字符在文章开头,结尾和中间都出现过,那么这段字符就可以被认为是一个“经典段”。
    现在小Y给你一篇文章,他想知道最长的一段“经典段”长度是多少?
    注意,这里要求经典串至少出现三次,分别作为文章的前缀,后缀,及既非前缀也非后缀。

    Input

    一行,给出一个由小写字母组成的字符串。

    Output

    输出满足题目要求的非空子串,如果不存在这样的非空子串输出。(字符串严格匹配,不含双引号)

    Sample Input

    fixprefixsuffix

    Sample Output

    fix

    HINT

    字符串长度leq1000000

    Solution

    kmp预处理出这个字符串a能与后缀匹配的前缀最长子串b.

    nxt[;]数组求出b中哪些下标i使得b[1..i]a后缀.

    kmp匹配a[2...|a|-1]b,求出最大的i使得b[1..i]a后缀.

    #include<cmath>
    #include<ctime>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 1000005
    using namespace std;
    int nxt[N],n,ans;
    bool f[N];
    char a[N],b[N],c[N];
    inline void get_nxt(char b[],int n){
        for(int i=2,j=0;i<=n;++i){
            while(j&&b[j+1]!=b[i]) j=nxt[j];
            if(b[j+1]==b[i]) ++j;
            nxt[i]=j;
        }
    }
    inline void kmp1(){
        int k=0;
        for(int i=1,j=0;i<n;++i){
            while(j&&b[j+1]!=a[i]) j=nxt[j];
            if(b[j+1]==a[i]) ++j;
            if(i==n-1) k=j;
        }
        while(k){
            //printf("k=%d
    ",k); 
            f[k]=true;k=nxt[k];
        }
    }
    inline int kmp2(){
        int ret=0;get_nxt(a,n);
        for(int i=2,j=0;i<n;++i){
            while(j&&c[j+1]!=c[i]) j=nxt[j];
            if(c[j+1]==c[i]) 
                if(f[++j]) ret=max(ret,j);
        }
        return ret;
    }
    inline void print(){
        printf("Y can't find any classical string.
    ");
    }
    inline void init(){
        scanf("%s",c+1);n=strlen(c+1);
        if(n<3){
            print();return;
        }
        for(int i=n,j=1;i>1;--i,++j)
            b[j]=c[i];
        for(int i=n-1,j=1;i;--i,++j)
            a[j]=c[i];
        get_nxt(b,n-1);kmp1();
        ans=kmp2();
        if(ans){
            for(int i=ans;i;--i)
                printf("%c",b[i]);
            printf("
    ");
        }
        else print();
    }
    int main(){
        freopen("article.in","r",stdin);
        freopen("article.out","w",stdout);
        init();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    面试高频题:讲讲项目中的技术难点?
    看完本文还不会安装mysql吗?
    spring中如何向一个单例bean中注入非单例bean
    一次性讲清楚spring中bean的生命周期之三:bean是如何实例化的
    java面试一日一题:字节java后端工程师面试题
    VMware 安装 Centos 7 虚拟机配置网络
    基于 Blazor 打造一款实时字幕
    MVP on Board 没用小技巧 👌
    数据治理实践:元数据管理架构的演变
    Apache Superset1.2.0教程(四)—— CentOS环境安装
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6049255.html
Copyright © 2011-2022 走看看