KMP算法的next数组,存放的是子字符串(长度较小的字符串)的最长前缀后缀公共元素长度!!!
最常用的求next数组,也可以用来求字符串可能存在的循环节:
void getnext(char s[],int len){ int j=0,k=-1; next[0] = -1; while(j < len){ if(k == -1 || s[j] == s[k]) next[++j] = ++k; else k = next[k]; } } //1231231234 //-1 0 0 0 1 2 3 4 5 6
另一种优化了的求next数组
void getnext(char s[],int len){ int j=0,k=-1; next[0] = -1; while(j < len){ if(k == -1 || s[j] == s[k]){ j++,k++; if(s[j] != s[k]) next[j] = k; else next[j] = next[k]; } else k = next[k]; } }
kmp算法代码:
#include <bits/stdc++.h> using namespace std; const int maxx = 100010; int next[maxx]; char s1[maxx],s2[maxx]; void getnext(char s[],int len){ int j=0,k=-1; next[0] = -1; while(j < len){ if(k == -1 || s[j] == s[k]){ j++,k++; if(s[j] != s[k]) next[j] = k; else next[j] = next[k]; } else k = next[k]; } } int kmp(char s1[],char s2[]) { getnext(s2,strlen(s2)); int i=0,j=0; int l1 = strlen(s1),l2 = strlen(s2); while(i < l1 && j < l2){ if(j == -1 || s1[i] == s2[j]) i++,j++; else j = next[j]; } if(j == l2) return i-j; return -1; } int main() { scanf("%s",s1); scanf("%s",s2); cout<<kmp(s1,s2); return 0; }