KMP算法笔记
【简述】:
kmp算法:
1 kmp是用来匹配字符串,只能够匹配单一的字符串
2 kmp的算法的过程:
1:假设文本串的长度为n,模式串的长度为m;
2:先例用O(m)的时间去预处理next数组,next数组的意思指的是当前的字符串匹配失败后要转到的下一个状态;
3:利用o(n)的时间去完成匹配;
3 时间复杂度为o(n+m)即o(n);
【例题】:
1. 可重叠匹配:j=nxt[j]
求模式串在主串中出现的次数,可重叠【HDU 1686 Oulipo】
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <deque> #include <ctime> #define fst first #define sec second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ms(a,x) memset(a,x,sizeof(a)) typedef long long LL; #define pi pair < int ,int > #define MP make_pair using namespace std; const double eps = 1E-8; const int dx4[4]={1,0,0,-1}; const int dy4[4]={0,-1,1,0}; const int inf = 0x3f3f3f3f; const int N=1E4+7; string a,b; int ans; int nxt[N]; void getnxt( int n) { int i = 0; int j = -1; nxt[0] = -1; while (i<n) if (j==-1||b[i]==b[j]) nxt[++i]=++j; else j = nxt[j]; } void kmp( int n,int m) { int i = 0 ; int j = 0 ; getnxt(m); // for ( int i = 0 ; i < m ; i++) cout<<i<<" "<<nxt[i]<<endl; while (i<n) { if (j==-1||a[i]==b[j]) i++,j++; else j = nxt[j]; if (j==m) ans++,j=nxt[j]; } } int main() { ios::sync_with_stdio(false); int T; cin>>T; while (T--) { cin>>a>>b; swap(a,b); int la = a.length(); int lb = b.length(); ans = 0 ; kmp(la,lb); cout<<ans<<endl; } return 0; }
2. 不可重叠匹配:j=0
问模式串在文本串中出现的次数,不允许重叠【HDU 2087 剪花布条】
//不是j=nxt[j],因为不能重复,只要每次找到的时候j=0一下就好。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <deque> #include <ctime> #define fst first #define sec second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define ms(a,x) memset(a,x,sizeof(a)) typedef long long LL; #define pi pair < int ,int > #define MP make_pair using namespace std; const double eps = 1E-8; const int dx4[4]={1,0,0,-1}; const int dy4[4]={0,-1,1,0}; const int inf = 0x3f3f3f3f; const int N=1E4+7; string a,b; int ans; int nxt[N]; void getnxt( int n) { int i = 0; int j = -1; nxt[0] = -1; while (i<n) if (j==-1||b[i]==b[j]) nxt[++i]=++j; else j = nxt[j]; } void kmp( int n,int m) { int i = 0 ; int j = 0 ; ans=0; getnxt(m); // for ( int i = 0 ; i < m ; i++) cout<<i<<" "<<nxt[i]<<endl; while (i<n) { if (j==-1||a[i]==b[j]) i++,j++; else j = nxt[j]; if (j==m) ans++,j=0; } } int main() { ios::sync_with_stdio(false); while(cin>>a>>b) { ans=0; if(a[0]=='#'||b[0]=='#') break; int len1=a.size(); int len2=b.size(); kmp(len1,len2); printf("%d ",ans); } return 0; }