hdu4763(KMP的应用)

该博客探讨如何利用KMP算法寻找给定字符串中符合条件的最长子串,即该子串既是前缀也是后缀,且在中间至少再次出现,所有出现的子串不重叠。通过构建失配数组并进行遍历判断,实现问题的解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给一个字符串,问最长的一个子串A,他是前缀,同时是后缀,并且中间也出现过A。并且出现的三个A都不没有重叠部分。


解法:先KMP求出失配数组,然后将所有的是后缀且是前缀的打上标记,然后遍历整个next数组,(对于每个位置的next来说,一直next向前取就是找到此前缀的一个个是整个字符串前缀的后缀,比较绕)暴力枚举判断每个串的所有匹配前缀的后缀是否合法。


代码:

/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>

using namespace std;

#define eps 1e-8
typedef long long LL;

int next1[1001000];
void getNext(char *s)
{
    int len=strlen(s);
    int i=0;
    int j=next1[0]=-1;
    while(i<len)
    {
        while(j!=-1&&s[i]!=s[j]) j=next1[j];
        next1[++i]=++j;
    }
}

char s[1000100];
bool rem[1000100];

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(rem,0,sizeof rem);
        scanf("%s",s);
        getNext(s);
        int len=strlen(s);
        int tool=next1[len];
        while(tool)
        {
            rem[tool]=1;
            tool=next1[tool];
        }
        int out=0;
        for(int i=len-1; i>1; i--)
        {
            int t=i;
            while(t!=-1)
            {
                if(rem[next1[t]]&&len-next1[t]>=i&&i-next1[t]>=next1[t])
                {
                    out=max(out,next1[t]);
                    break;
                }
                t=next1[t];
            }
        }
        cout<<out<<'\n';
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值