KMP

大概就是处理两个字符串的匹配问题
就是匹配失败后尽量避免不需要的匹配
比如说:
模式串:(abcabc)
文本串:(abcabdababcabc)
在第六个字符匹配失败后,应该跳到模式串中的'(b)',然后用下一位与这个失配的字符进行比较。而不要从头开始一位一位的比较。
(nxt[])表示的是当前这个字符失配之后跳到第几个字符

之前按自己的写法总会出现一些莫名其妙的错误,现在纠正一下。

  1. 字符串下标从(1)开始.
  2. (nxt[i]=j) 表示的是第(i+1)个字符与文本串匹配失败后跳到第(j)个字符,从第(j+1)个字符开始匹配。(也就是说第(j)个字符是匹配成功的)
  3. (nxt[1]=0)(第一个字符匹配失败后就跳到(0),然后继续匹配第(0+1=1)个字符)

luogu P3375
code:


#include<bits/stdc++.h>
#define N 1200000 
using namespace std;
char T[N]; //文本串 
char P[N]; //模式串
int nxt[N];
int ans[N];
int main(){
	scanf("%s%s",T+1,P+1);
	int n=strlen(T+1);
	int m=strlen(P+1);
	int j;
	j=nxt[1]=0;
	for(int i=2;i<=m;i++){
		while(P[i]!=P[j+1]&&j) j=nxt[j];
		if(P[i]==P[j+1]) j++;
		nxt[i]=j;//处理之后才赋值
	} 
	j=0;
	for(int i=1;i<=n;i++){
		while(T[i]!=P[j+1]&&j) j=nxt[j];
		if(T[i]==P[j+1]) j++;
		if(j==m){
			printf("%d
",i-m+1);
			j=nxt[j];//如果找到匹配的字符串之后要删去就是j=0;
		}
	}
	for(int i=1;i<=m;i++) printf("%d ",nxt[i]);
} 

原文地址:https://www.cnblogs.com/doublety/p/11519319.html