zoukankan      html  css  js  c++  java
  • 【NOIP2012模拟8.20】Memory

    题目

    话说某一天,CD在爬树的时候发现了树干上有一大串奇怪的符文,于是好奇的CD就从头到尾看了一遍。看完一遍以后CD觉得,最后一段文字好像很眼熟,好像在前面见过。对于CD来说,一开始看到的符文会印象特别深刻,而且这段符文要出现多次,CD才会觉得眼熟。
    其实现在就是,CD会告诉你他看到的符文具体是什么,你要告诉CD,这段符文里最长的既是前缀又是后缀还在中间某个地方出现过(非前缀非后缀的出现)的最长的子串是什么。

    分析

    研究了一下kmp,发现
    (next)数组表示在字符串(s)中,(s[1...next_{j}]=s[j-next_{j}+1...j])
    那么,在kmp中如果出现了j,就表示(s[1...j])一定在中间出现过(因为是中间,所以j!=n),用标记数组bz记录下来。
    接着就要判断后缀是否在前面出现就可以啦,细节自己研究。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=1010000;
    using namespace std;
    int next[N]={0},n;
    bool bz[N]={0};
    char s[N];
    int main()
    {
        freopen("2964.in","r",stdin);
        freopen("2964.out","w",stdout);
        scanf("%s
    ",s+1);
        n=strlen(s+1);
        int j=0;
        for(int i=2;i<=n;i++)
        {
            while(j && s[j+1]!=s[i]) j=next[j];
            if(s[j+1]==s[i]) j++;
            next[i]=j;
            if(i!=n) bz[j]=true;
        }
        while(j && !bz[j]) j=next[j];
        if(bz[j]) 
            for(int i=1;i<=j;i++) printf("%c",s[i]);
                else 
                    printf("CD can't remember anything.");
    }
    
    
  • 相关阅读:
    那些离不开的 Chrome 扩展插件
    Spring Boot 实战 —— 入门
    Maven 学习笔记
    Linux lvm 分区知识笔记
    Linux 双向 SSH 免密登录
    CentOS Yum 源搭建
    Ubuntu 系统学习
    iOS 测试三方 KIF 的那些事
    Swift 网络请求数据与解析
    iOS Plist 文件的 增 删 改
  • 原文地址:https://www.cnblogs.com/chen1352/p/9043443.html
Copyright © 2011-2022 走看看