[ACW]831.KMP字符串
Posted sumaywlx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ACW]831.KMP字符串相关的知识,希望对你有一定的参考价值。
题目描述:求出模板串P在模式串S中所有出现的位置的起始下标。
tips:
1.next数组多求一位,求出整个P串的最大前后缀匹配长度。
2.当匹配成功时,p串向后推多少?此时s串的指针i1已经指向完全匹配的下一位了,只需要i2跳跃到整个串最大前后缀匹配长度指示的位置开始比较就行;用反证法假设证推矛盾。
3.位置下标从0开始,长度与下标的对应。
4.next数组有递推的感觉,刚开始的处理,比如i-1和cn=0的处理,就很巧妙。
//1.首A代码,尽管写的比较丑,还是留影纪念下吧
//2.卡了好久的一个点是,自己觉得逻辑没有错误,输出就是不对,是什么原因呢??
//输出语句的位置没放在while循环里
//3.自己独立完成推了第一次匹配成功后,该怎么接着继续匹配?
//我的解法是求next数组时,多求一位,求出整个P串的最长前缀和最长后缀的匹配长度
//匹配成功时,i1已经指向完全匹配位置的下一位,
//4.用反证法进行证明:i2指针的跳跃和被否定掉的位置不可能匹配成功,即不可能出现更长的前缀和后缀相匹配
//5.一路都相等;没配上之前,两个字符串都一样
//6.注意比较完之后下标指针i1、i2的更新
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N=10010;
const int M=100010;
char p[N],s[M];
int ne[N];
int n,m;
void getne(char* p){
int pLen=strlen(p);
ne[0]=-1;
ne[1]=0;
int i=2;
int cn=0;
while(i<=pLen){
if(p[i-1] == p[cn]){
ne[i++]=++cn;
}else if(cn > 0){
cn=ne[cn];
}else{
ne[i++]=0;
}
}
/*
for(int i=0;i<=pLen;i++){
printf("%d ",ne[i]);
}
*/
return ;
}
int main(){
cin>>n>>p>>m>>s;
getne(p);
int pLen=strlen(p);
int sLen=strlen(s);
int i1=0;//甲指针
int i2=0;//乙指针
for(;i1<m;i1++){
while(i1<sLen && i2<pLen){
if(s[i1] == p[i2]){
i1++;
i2++;
}
else if(ne[i2]== -1)// 思考ne[i2]什么时候等于-1?当ne[i2]==-1时,i2已经指向了p串开头0
{
i1++;
}
else{
i2=ne[i2];
}
if(i2 == pLen){
printf("%d ",i1-pLen);
i2=ne[i2];
}
}
}
return 0;
}
ps:kmp算是才刚刚解锁,学习花了大概一周的时间
ref:左神,以及网上的博客,致谢!
以上是关于[ACW]831.KMP字符串的主要内容,如果未能解决你的问题,请参考以下文章