Passward

来源:互联网 发布:艾瑞咨询数据 编辑:程序博客网 时间:2024/06/04 17:55

题面

  题目描述

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

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

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

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

  输入格式:

  仅一行,字符串 s。

  输出格式:

  如题所述

  样例输入

  fixprefixsuffix

  样例输出:

  fix

  数据范围:

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

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


思路

  考场想出下面这个算法,时间复杂度什么的都没有保证。但数据都很水, 所以大胆搜索。

  先定义结构体,num为原数组下标, step为当前以此下标匹配成功的长度。

struct Step{    int num;    int step;}tmp;

  b数组维护值为首字母的位置的下标:

for (int i = 0;i < y;i ++)        if (ch[x] == ch[i])            b.push(Step{i, 0});

  若队列大小小于2,则必无解:

if (b.size() <= 2)    {        printf("Just a legend");        return 0;    }

  然后每次将匹配长度向后推进一个,比较判断此时队列中所有元素是否仍然可行;将可行解再push进队列:

while (b.size() >= 3)    {        tmpb = b.front(); b.pop();        if (tmpb.step >= now)            now ++;        if (ch[tmpb.num + now - 1] == ch[x + now - 1])        {            b.push(Step{tmpb.num, now});            if (tmpb.num + now - 1 == y - 1 && b.size() >= 3)                ans = max(ans, now);        }    }

  这里可以更新答案:若此时的匹配存在已经匹配到末位的元素(因为从首位开始匹配,所以匹配到末位一定为原串的后缀)并且当前已经匹配成功的元素,那么就将答案更新为此元素的step:

if (ch[tmpb.num + now - 1] == ch[x + now - 1])        {            b.push(Step{tmpb.num, now});            if (tmpb.num + now - 1 == y - 1 && b.size() >= 3)                ans = max(ans, now);        }

  如果结果未被更新,便无解:

if (ans == -1)    {        printf("Just a legend");        return ;    }

  其实听说正解为KMP,但考场实测24MS,只比KMP慢8MS。

但其实还是很好构造出卡这个算法的数据。
如若有一连串的“aaaaaaaaaaaaaaaaaaa”,那每次都会只否定一组,接近Θ(n2) 的时间复杂度。

代码

#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <queue>#include <iostream>#define LL long longusing namespace std;const size_t MN = 100005;struct Step{    int num;    int step;}tmp;char ch[MN];int x, y;queue < Step > b;void solve(){    Step tmpb;    int now = 0, ans = -1;    while (b.size() >= 3)    {        tmpb = b.front(); b.pop();        if (tmpb.step >= now)            now ++;        if (ch[tmpb.num + now - 1] == ch[x + now - 1])        {            b.push(Step{tmpb.num, now});            if (tmpb.num + now - 1 == y - 1 && b.size() >= 3)                ans = max(ans, now);        }    }    if (ans == -1)    {        printf("Just a legend");        return ;    }    for (int i = 0;i < ans;i ++)        putchar(ch[i]);}int main(){    scanf("%s", ch);    y = strlen(ch);    if (y <= 2)    {        printf("Just a legend");        return 0;    }    tmp.step = 1;    for (int i = 0;i < y;i ++)    {        if (ch[x] == ch[i])            b.push(Step{i, 0});    }    if (b.size() <= 2)    {        printf("Just a legend");        return 0;    }    solve();    return 0;}
原创粉丝点击