[模板] KMP算法/Border

KMP 算法

KMP (Knuth-Morris-Pratt) 算法是一种在线性时间内匹配文本串和模式串的算法.

称字符串的 Border 集合为

\[\operatorname {Border} (S) = \{Pre_S(j) | Pre_S(j) = Suf_S(n - j + 1) \land j \not= n \} \]

称字符串 \(S\) 的最长 Border 为 \(fail(S)\), 或者 \(next(S)\). 容易发现递归枚举 \(fail(S), fail(fail(S)), \dotsc\) 可以得到 \(S\)\(\operatorname {Border}\) 集合.

把每个位置 \(p\) 连向 \(fail(p)\) (包括 \(0\) 号节点), 可以得到一棵以 \(0\) 号节点为根的树, 称为 Border tree.

KMP 算法可以在线性时间内得到字符串 \(S\) 每个前缀的 \(fail\) 函数, 并可以利用它进行字符串的匹配.

求 Border 和匹配

int n,m;
char s1[nsz],s2[nsz];

int nxt[nsz];
void getnext(char *s,int n){
	int l=0; //l means the length of prefix matched
	nxt[1]=0;
	rep(i,2,n){
		while(l&&s[l+1]!=s[i])l=nxt[l];
		if(s[l+1]==s[i])++l;
		nxt[i]=l;
	}
}

int pl[nsz],pp=0;
void match(){ //s2->s1
	pp=0;
	int l=0; // the length of prefix of m matched
	rep(i,1,m){
		while(l&&s2[l+1]!=s1[i])l=nxt[l];
		if(s2[l+1]==s1[i])++l;
		if(l==n){pl[++pp]=i-l+1;l=nxt[l];}
	}
}
posted @ 2019-07-02 10:11  Ubospica  阅读(971)  评论(0编辑  收藏  举报