P2375 [NOI2014]动物园

本文深入探讨了KMP算法在字符串匹配中的应用,详细解释了如何通过维护一个额外的数组来加速匹配过程,避免了传统暴力匹配的重复计算,从而将复杂度降低到O(n)。同时,文章提供了完整的代码实现,帮助读者更好地理解KMP算法的工作原理。

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

传送门

如果不考虑不重叠的限制的话,$num[i]$ 是很容易求的:

scanf("%s",s+1);
int j=0; n=strlen(s+1); num[1]=1;
for(int i=2;i<=n;i++)
{
    while(j&&s[j+1]!=s[i]) j=f[j];
    f[i]= s[j+1]==s[i] ? ++j : 0;
    num[i]=num[j]+1;
}

对于限制,考虑每个点都暴力跳 $fail$,直到跳到合法为止

for(int i=1,j=i;i<=n;i++,j=i)
{while(j>i/2) j=f[j];
    ans=1ll*ans*(num[j]+1)%mo;
}

但是这种做法可以被卡到 $n^2$($aaaaaaaaaa...$ 这样的数据)

考虑 $KMP$ 时怎么维护 $fail$ 的,搞一个指针 $j$,指向当前上一个位置的 $fail$,这样就不用每次都重新跳了

那我们维护 $num$ 也可以考虑这种操作,然后复杂度就是 $O(n)$

具体看代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=2e6+7,mo=1e9+7;
int n,f[N],num[N],ans=1;
char s[N];
int main()
{
    int T=read();
    while(T--)
    {
        scanf("%s",s+1);
        int j=0; n=strlen(s+1); ans=num[1]=1;
        for(int i=2;i<=n;i++)
        {
            while(j&&s[j+1]!=s[i]) j=f[j];
            f[i]= s[j+1]==s[i] ? ++j : 0;
            num[i]=num[j]+1;
        }
        j=0;
        for(int i=2;i<=n;i++)
        {
            while(j&&s[j+1]!=s[i]) j=f[j];
            if(s[j+1]==s[i]) j++;
            while(j>i/2) j=f[j];
            ans=1ll*ans*(num[j]+1)%mo;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/LLTYYC/p/11334536.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值