KMP 模板(修訂,更易懂)
阿新 • • 發佈:2020-11-16
KMP 模板(修訂,更易懂)
之前一篇部落格簡單介紹了KMP的原理,但當時寫的模板兩個字串陣列都是從下標為0開始的,邏輯有些混亂.
這次修改了x,y下標從1開始,感覺更加自然.
#include <bits/stdc++.h> using namespace std; const int N = 1e6+5; const int M = 1e4+5; int xlen,ylen; int pre[M]; char x[M]; char y[N]; // x 是模式串,y 是文字串,均從1開始 void read_string(){ scanf("%d%d",&xlen,&ylen); scanf("%s",x+1); scanf("%s",y+1); } // pre[i]: x串的長度為i的子串的公共前後綴長度 void get_pre(){ pre[0] = -1; pre[1] = 0; for(int i = 2; i <= xlen; ++i){ if(x[i] == x[pre[i-1]+1]){ pre[i] = pre[i-1] + 1; }else{ int ptr = pre[i-1] + 1; while(ptr >= 1 && x[ptr] != x[i]){ ptr = pre[ptr-1] + 1; } pre[i] = ptr; } } } int kmp_match(int ans[]){ int cnt = 0; int xptr = 1,yptr = 1; while(xptr <= xlen && yptr <= ylen){ if(xptr == 0 || x[xptr] == y[yptr]){ ++xptr; ++yptr; }else{ xptr = pre[xptr-1] + 1; } if(xptr == xlen + 1){ // 注意此時x和y都已經向後移位了 ans[++cnt] = yptr - xptr + 1; xptr = pre[xptr-1] + 1; } } return cnt; } int main(){ read_string(); get_pre(); for(int i = 0; i <= xlen; i++){ printf("pre[%d] = %d\n",i,pre[i]); } int ans[10]; int cnt = kmp_match(ans); for(int i = 1; i <= cnt; i++){ printf("%d\n",ans[i]); } system("pause"); return 0; }