#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; }
makefail()函数就是打next数组,调用KMP函数之前一定记得要先调用一遍makefail()
s是待匹配串,而t是模式串,ls和lt就是各自的长度,i是从下标为i+1处开始进行匹配,longest是所能匹配到的最长t的子串或其本身开始的位置,lp是所能匹配到的最长t的子串或其本身的长度
需要注意以上所说的i和longest的位置,都是字符在匹配串中的下标位置加一,即正常理解的第几个字符,而不是匹配串下标!但kmp函数返回值仍然是下标。