KMP模板

发布时间 2023-11-21 16:50:22作者: CRt0729
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3+10,inf = 0x3f3f3f3f;
int nex[N]; //nex[j]的意思是当子串的第j个字符和主串的第i个字符不匹配时,我们应该从子串的nex[j]字符开始重新匹配 
string a,b;
/*
kmp指针回退 j = nex[j - 1]
根本原因:子串的指针j总是表示我们即将要匹配子串的第j个字符,所以如果子串[j]和主串[i]不匹配
那么我们自然是要从子串的nex[j - 1]字符开始重新匹配
*/
void get_next(string b)
{
    int j = 0; //前缀末尾
    for(int i = 1; i < b.size(); i++)
    {
        //指针回退
        while(j > 0 && b[i] != b[j]) j = nex[j - 1];
        //前缀和后缀的末尾相同则计数 
        if(b[j] == b[i]) j++;
        nex[i] = j; 
    } 
}
int kmp(string a,string b) //获取子串在主串中第一次出现的位置
{
    int j = 0; //子串指针j,主串指针i 
    for(int i = 0; i < a.size(); i++)
    {
        while(j > 0 && a[i] != b[j]) j = nex[j - 1]; //3.指针回退 
        if(a[i] == b[j]) j++; //1.当前子串和主串匹配,那么继续匹配子串的下一个 
        if(j == b.size()) //2.如果匹配完了,那么成功匹配的位置是:主串当前长度i - 子串长度b.size() + 1
        {
            //这里是返回子串在主串中第一次出现的位置,如果要解决其他问题,可以在这里进行修改 
            return i - b.size() + 1; 
        }
    }
    return -1; //没有匹配成功返回-1 
}
int main()
{
    getline(cin,a);
    getline(cin,b);
    get_next(b);
    cout << kmp(a,b);
    return 0;
}