#include<bits/stdc++.h> using namespace std; const int N = 1000100,M = 1100; int next[N]; void getNext(char s[]) //找next数组 { int len=strlen(s+1); //确保调用s中的元素的时候是从s[1]开始而不是s[0],因为next数组从1开头 for (int i=2,j=0;i<=len;i++) { //从第二个元素开始匹配,因为第一个元素一定不存在前缀,j=0是因为next[0]=0 //next数组记录的是到第i位为止前面这段字符串的前缀和后缀的共有部分的长度 while (j && s[i]!=s[j+1]) j=next[j]; //就是移动过程 if (s[i]==s[j+1]) j++; //如果匹配就继续 next[i]=j; //表明第i位的next[i]的值是j } } void kmp(char s[],char t[]) //在s中找t { int lens=strlen(s+1),lent=strlen(t+1); //同上 for (int i=1,j=0;i<=lens;i++) { //注意是从s的第一位开始匹配 while (j && s[i]!=t[j+1]) j=next[j]; //经典移动过程 if (s[i]==t[j+1]) j++; //如果匹配就继续 if (j==lent) printf("%d ",i-lent+1); //输出(现在的位置-需要寻找的字符串的长度+1)就是这个字符串第一次出现的位置 } } int main() { char a[N],b[M]; cin>>a+1>>b+1; getNext(b); kmp(a,b); return 0; //洛谷评测改c++别用c++11,用流输入输出要关流输入 ios::sync_with_stdio(false) }
来自题解