KMP
大概就是处理两个字符串的匹配问题
就是匹配失败后尽量避免不需要的匹配
比如说:
模式串:\(abcabc\)
文本串:\(abcabdababcabc\)
在第六个字符匹配失败后,应该跳到模式串中的'\(b\)',然后用下一位与这个失配的字符进行比较。而不要从头开始一位一位的比较。
\(nxt[]\)表示的是当前这个字符失配之后跳到第几个字符
之前按自己的写法总会出现一些莫名其妙的错误,现在纠正一下。
- 字符串下标从\(1\)开始.
- \(nxt[i]=j\) 表示的是第\(i+1\)个字符与文本串匹配失败后跳到第\(j\)个字符,从第\(j+1\)个字符开始匹配。(也就是说第\(j\)个字符是匹配成功的)
- \(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\n",i-m+1);
j=nxt[j];//如果找到匹配的字符串之后要删去就是j=0;
}
}
for(int i=1;i<=m;i++) printf("%d ",nxt[i]);
}