大概就是处理两个字符串的匹配问题
就是匹配失败后尽量避免不需要的匹配
比如说:
模式串:(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
",i-m+1);
j=nxt[j];//如果找到匹配的字符串之后要删去就是j=0;
}
}
for(int i=1;i<=m;i++) printf("%d ",nxt[i]);
}