zoukankan      html  css  js  c++  java
  • [DBSDFZOJ 多校联训] Password

    Password

    password.in/.out

    描述

    你来到了一个庙前,庙牌上有一个仅包含小写字母的字符串 s。

    传说打开庙门的密码是这个字符串的一个子串 t,并且 t 既是 s 的前缀又是 s 的后缀并且还在 s 的中间位置出现过一次。

    如果存在这样的串,请你输出这个串,如有多个满足条件的串,输出最长的那一个。

    如果不存在这样的串,输出"Just a legend"(去掉引号)。

    输入格式

    仅一行,字符串 s。

    输出格式

    如题所述

    样例输入

    fixprefixsuffix

    样例输出:

    fix

    数据范围

    对于 60%的数据, s 的长度<=100

    对于 100%的数据, s 的长度<=100000

    看到"同时是前缀与后缀的串的长度"可能大家都能想到 $KMP$ 算法w

    但是题目对于这个串有一定限制: 必须在中间出现过至少一次. 所以我们计算出这个串的长度之后还要拿着这个串进原串匹配一发, 如果匹配次数达到 $3$ 或以上就说明这个串除了在两端出现过之外还在中间出现了至少一次. 如果没有在中间出现则在刚刚验证失败的子串内接着找同时是这个串前缀与后缀的串的最大长度.

    也就是说先求 $KMP$ 中的失配边, 然后在不符合题意的时候一直跳失配边就好了.

    跳到最后还是没有匹配到说明无解.

    (考试的时候输入数据神特么文件尾没有空行(╯‵□′)╯︵┻━┻逐字符读入直接死循环然后本来能A的题...裱死出数据的家伙)

    参考代码:

    GitHub

     1 #include <cctype>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <iostream>
     6 #include <algorithm>
     7 
     8 const int MAXN=100010;
     9 
    10 int len;
    11 int fail[MAXN];
    12 char buffer[MAXN];
    13 
    14 int Read(char*);
    15 void Print(char*,int);
    16 void KMP(char*,int*,int);
    17 int Match(char*,int,char*,int,int*);
    18 
    19 int main(){
    20     scanf("%s",buffer);
    21     len=strlen(buffer);
    22     KMP(buffer,fail,len);
    23     for(int k=fail[len];k>0;k=fail[k]){
    24         if(Match(buffer,len,buffer,k,fail)>2){
    25             Print(buffer,k);
    26             return 0;
    27         }
    28     }
    29     puts("Just a legend");
    30     return 0;
    31 }
    32 
    33 void KMP(char* buf,int* f,int len){
    34     int j=0,k=-1;
    35     f[0]=-1;
    36     while(j<len){
    37         if(k==-1||buf[j]==buf[k]){
    38             f[++j]=++k;
    39         }
    40         else k=f[k];
    41     }
    42 }
    43 
    44 int Match(char* buf,int lb,char* ptn,int lp,int* f){
    45     int j=0,ans=0;
    46     for(int i=0;i<lb;i++){
    47         while(j>0&&buf[i]!=ptn[j]) 
    48             j=f[j];
    49         if(buf[i]==ptn[j])
    50             j++;
    51         if(j==lp){
    52             ans++;
    53             j=f[j];
    54         }
    55     }
    56     return ans;
    57 }
    58 
    59 inline void Print(char* buf,int len){
    60     for(int i=0;i<len;i++){
    61         putchar(buf[i]);
    62     }
    63     putchar('
    ');
    64 }
    65 
    66 inline int Read(char* buf){
    67     int pos=0;
    68     do{
    69         buf[pos]=getchar();
    70     }while(isspace(buf[pos]));
    71     while(!isspace(buf[pos])&&buf[pos]!=EOF){
    72         buf[++pos]=getchar();
    73     }
    74     buf[pos]='';
    75     return pos;
    76 }
    Backup

  • 相关阅读:
    词法分析
    HTTP学习笔记
    Servlet入门
    UDP与TCP的区别
    C语言实现血型查询系统
    Mysql的索引、回表查询及覆盖索引浅析
    ReentranLock浅析
    CAS是个什么鬼?
    synchronize和volatile 小知识点总结
    写一个简单的阻塞队列
  • 原文地址:https://www.cnblogs.com/rvalue/p/7300024.html
Copyright © 2011-2022 走看看