ACM模板——KMP

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define _for(i,a,b) for(int i = (a);i < (b);i ++)
const int maxn = 50003; 

int fail[maxn];
void makefail(char *t,int lt)
{
    --t;
    for(int i = 1,j = 0;i <= lt;i ++,j ++)
    {
        fail[i] = j;
        while(j>0 && t[i]!=t[j]) j = fail[j];
    }
}

//match pattern T in S
int kmp(char *s,int ls,char *t,int lt,int i,int &longest,int &lp)
{
    longest = lp = 0;--s;--t;
    for(int j = 1;i <= ls;i ++,j ++)
    {
        while(j>0 && s[i]!=t[j]) j = fail[j];
        if(j>longest) {longest = j;lp = i-j;}
        if(j==lt) return i-lt;
    }
    return -1;
}

int main()
{
    char s[100] = "ababaaaaaaab";
    char t[100] = "babababa";
    
    int ls = strlen(s),lt = strlen(t);
    int longest,lp;
    makefail(t,lt);
    _for(i,0,lt)
        cout << fail[i] << " ";
    cout << endl;
    cout << kmp(s,ls,t,lt,4,longest,lp) << endl;
    cout << longest << " " << lp << endl;
    return 0;
}
KMP

makefail()函数就是打next数组,调用KMP函数之前一定记得要先调用一遍makefail()

s是待匹配串,而t是模式串,ls和lt就是各自的长度,i是从下标为i+1处开始进行匹配,longest是所能匹配到的最长t的子串或其本身开始的位置,lp是所能匹配到的最长t的子串或其本身的长度

需要注意以上所说的i和longest的位置,都是字符在匹配串中的下标位置加一,即正常理解的第几个字符,而不是匹配串下标!但kmp函数返回值仍然是下标。

猜你喜欢

转载自www.cnblogs.com/Asurudo/p/10493633.html