题目链接:https://www.luogu.org/problem/P3375
就是一个裸的kmp,还记得很久很久之前,第一次看kmp,看了一天都没看懂,还是浮躁加效率太低了,kmp好好看其实根本就不难
模板码住吧。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; const int inf=0x3f3f3f3f; typedef long long ll; #define meminf(a) memset(a,0x3f,sizeof(a)) #define mem0(a) memset(a,0,sizeof(a)); char s1[maxn],s2[maxn]; int nxt[maxn];//用于记录当匹配到模式串的第i位之后失配,该跳转到模式串的哪个位置 int main(){ scanf("%s%s",s1+1,s2+1); //scanf("%s",s2+1); int len1=strlen(s1+1),len2=strlen(s2+1); //接下来求nxt数组,nxt数组仅由模式串本身决定 nxt[0]=0,nxt[1]=0;//第一位,第二位失配了,都只可能以第一位作为新的开头 int k=0; //k指向的是j指针下一步移动的位置 //cout<<233<<endl; for(int i=2;i<=len2;i++){ //这里是从模式串的第二位开始匹配的 while(s2[i]!=s2[k+1]&&k!=0) k=nxt[k]; if(s2[i]==s2[k+1]) nxt[i]=++k; } k=0; for(int i=1;i<=len1;i++){ while(k&&s1[i]!=s2[k+1]) k=nxt[k];//如果不匹配,则利用nxt数组往回跳 if(s1[i]==s2[k+1])k++;//如果相等了,则匹配下一位 if(k==len2)printf("%d\n",i-len2+1); //如果相等了,我们就输出起始位置 } for(int i=1;i<len2;i++)printf("%d ",nxt[i]); printf("%d\n",nxt[len2]); return 0; }