Z Algorithm(后缀匹配)

本文深入解析了Z算法,一种高效求解字符串匹配问题的方法,能在O(n)时间内计算出所有后缀与前缀的匹配长度。适用于求解多个子串与另一串的最长匹配长度,通过特殊字符连接两串实现匹配。代码示例展示了如何使用Z算法解决具体问题。

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

介绍

一个和马拉车算法很像的东西,可以O(n)O(n)O(n)求出一个串的所有后缀与前缀的匹配长度。

适用场合:

求出某个字符串的mmm个子串与另外一个串的最长匹配长度(从前往后或从后往前)

在这里插入图片描述
因为往后扩不会返回,右端点一直加,所以时间复杂度为O(N)O(N)O(N)


两个串的情况

如果要匹配两个串,串xxx的所有后缀匹配串yyy的前缀,只需要使用特殊字符将xxx连到yyy后面即可。


orginal link - http://acm.hdu.edu.cn/showproblem.php?pid=6629

题意:

求第二位置开始的后缀与前缀的公共串长度LLL∑min(L+1,pL)\sum min(L+1,pL)min(L+1,pL)pLpLpL为后缀长度)

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2019-08-20-11.00.34
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
const LL mod=1e9+7;
const int maxn=1e6+9;
LL rd(){ LL z=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')z=z*10+ch-'0',ch=getchar();
    if(last=='-')z=-z; return z;
}
/*_________________________________________________________head*/

char str[maxn];
int len;
int z[maxn];
void deal(){ // Z Algorithm
    int l=0,r=1;
    z[0]=0;
    rep(i,1,len-1){
        if(r>i)z[i]=min(z[i-l],r-i);
        if(z[i]+i>=r){
            l=i,r=z[i]+i;
            while(r<len&&str[r]==str[r-l])r++;
            z[i]=r-l;
        }
    }
    z[0]=len;
}

int main(){
    int t=rd();
    while(t--){
        gets(str);
        len=strlen(str);
        deal();
        LL sum=0;
        rep(i,1,len-1){
            if(!z[i])sum++;
            else if(z[i]==len-i)sum+=z[i];
            else sum+=z[i]+1;
        }
        printf("%lld\n",sum);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值