K匹配

K匹配

关键

左边界是上一个匹配的地方少一个点,有边界是无穷大。
也就是从左到右,左边可以包含右边,但是右边不能包含左边,就能保证不重复计算

代码

//左边可以包含右边,但是右边不可以包含左边就可以了
#include <bits/stdc++.h>
using  namespace std;
using ll=long long;
const int M=1e7+5;
 
int ne[M];
void init(string s) {
    int n=s.size();
    s='?'+s;
    for(int i=2,j=0;i<=n;i++) {
        while(j&&s[i]!=s[j+1])j=ne[j];
        if(s[i]==s[j+1])j++;
        ne[i]=j;
    }
}

vector<int>v;
void find(string s,string p) {
    int n=s.size(),m=p.size();
    s='?'+s,p='?'+p;
    for(int i=1,j=0;i<=n;i++) {
        while(j&&s[i]!=p[j+1])j=ne[j];
        if(s[i]==p[j+1])j++;
        if(j==m) {
            v.push_back(i-m+1);//输出匹配的其实位置
            j=ne[j];
        }
    }
}

int main() {
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int n,m;
    cin>>n>>m;
    string s,p;
    cin>>s>>p;
    init(p);
    v.push_back(0);
    find(s,p);
    ll ans=0;
    for(int i=1;i<v.size();i++)
        ans+=1ll*(v[i]-v[i-1])*(n-v[i]-m+2);
    cout<<ans;
    return 0;
}
posted @ 2023-01-12 18:29  basicecho  阅读(52)  评论(0)    收藏  举报