洛谷 P3375【模板】KMP字元匹配
阿新 • • 發佈:2018-12-11
題目描述
如題,給出兩個字串s1和s2,其中s2為s1的子串,求出s2在s1中所有出現的位置。
為了減少騙分的情況,接下來還要輸出子串的字首陣列next。
(如果你不知道這是什麼意思也不要問,去百度搜[kmp演算法]學習一下就知道了。)
輸入輸出格式
輸入格式:
第一行為一個字串,即為s1
第二行為一個字串,即為s2
輸出格式:
若干行,每行包含一個整數,表示s2在s1中出現的位置
接下來1行,包括length(s2)個整數,表示字首陣列next[i]的值。
輸入輸出樣例
輸入樣例#1: 複製
ABABABC
ABA
輸出樣例#1: 複製
1 3 0 0 1
說明
時空限制:1000ms,128M
資料規模:
設s1長度為N,s2長度為M
對於30%的資料:N<=15,M<=5
對於70%的資料:N<=10000,M<=100
對於100%的資料:N<=1000000,M<=1000000
樣例說明:
所以兩個匹配位置為1和3,輸出1、3
KMP的模板題,AC程式碼如下
#include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <iomanip> #include <string> #include <set> #include <map> #include <queue> #include <stack> #include <vector> #include <algorithm> #include <sstream> #include <cstring> using namespace std; const int MAX=1e6+7; char s[MAX],p[MAX]; int slen,plen; int next[MAX]; void getnext() { next[0]=-1; int k=-1; int j=0; while(j<plen) { if(k==-1||p[k]==p[j]) { k++; j++; next[j]=k; } else k=next[k]; } return ; } void kmp() { int i=0; int j=0; while(i<slen&&j<plen) { if(j==-1||s[i]==p[j]) { i++; j++; } else j=next[j]; if(j==plen) { cout<<i-j+1<<endl; i=i-j+1; j=0; } } return; } int main() { scanf("%s%s",s,p); slen=strlen(s); plen=strlen(p); getnext(); kmp(); for(int i=1;i<=plen;i++) cout<<next[i]<<" "; cout<<endl; return 0; }