B 题题解

K匹配

https://ac.nowcoder.com/acm/contest/7613/B

B 题

这里下标从 0 开始

考虑KMP找到模式串在文本串中的第一个位置。

假设在文本串中区间[i,j]能匹配。

根据乘法原理,那么每次有(i+1)*(n-j)。但是有重复的部分。

注意到每一次都把一类左端点的贡献都算了,所以记录一个变量ss表示当前已经计算过多少个左端点的贡献,在下一次计算时把可以得到的左端点个数减去ss即可。即为 (i+1-ss)*(n-j)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
inline int read(){
    int x=0,f=0,ch=getchar();
    while('0'>ch||ch>'9')f^=ch=='-',ch=getchar();
    while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
    return f?-x:x;
}
const int MAX=1e7+5;
string s,p;
int n,nex[MAX],ans,ss;
inline void init(){
    nex[0]=-1;
    int j=0,k=-1;
    while(j<p.length()){
        if(k==-1||p[j]==p[k])++j,++k,nex[j]=k;
        else k=nex[k];
    }    
}
inline void KMP(){
    int i=0,j=0;
    while(i<s.length()){
        if(j==-1||s[i]==p[j])++i,++j;
        else j=nex[j];
        if(j==p.length()){
            ans+=(i-p.length()+1-ss)*(s.length()-i+1);
            ss=i-p.length()+1;
        }
    }
}
int t,k;
signed main(){
    n=read(),k=read();
    cin>>s>>p;
    init();
    KMP();
    printf("%lld\n",ans);
    return 0;
}

全部评论

相关推荐

我见java多妩媚:大外包
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务