MP算法模板
void getfail(char* p,int* f){ int m=strlen(p); f[0]=0;f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j&&p[i]!=p[j])j=f[j]; f[i+1]=p[i]==p[j]?j+1:0; } } void find(char* ori,char* tar,int* f){ int n=strlen(ori);int m=strlen(tar); getfail(tar,f); int j=0; for(int i=0;i<n;i++){ while(j&&tar[j]!=ori[i])j=f[j]; if(tar[j]==ori[i])j++; if(j==m)printf("%d\n",i-m+1); } }
getfail函数建立失配边,在两串匹配失败时沿失配边走——为模板串寻找重新匹配的最理想(靠后)的位置
即求模板串前缀在后文中出现的长度跟位置?大概是这种感觉
find函数就是简单的匹配了,习惯origin原串,target目标串的记法。。
A - Number Sequence
HDU - 1711模板题,wa点在读入,空格会断%s,但一个个读会把符号读成一个字符(换成%d就过了
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxm=1e5+7; const int maxn=1e7+7; int ori[maxn]; int tar[maxm]; int f[maxm]; int m,n; int flag; void getfail(int* p,int* f){ f[0]=0;f[1]=0; for(int i=1;i<m;i++){ int j=f[i]; while(j && p[i]!=p[j])j=f[j]; f[i+1]=p[i]==p[j]?j+1:0; } } void find(int* ori,int* tar,int* f){ getfail(tar,f); int j=0; for(int i=0;i<n;i++){ while(j && tar[j]!=ori[i])j=f[j]; if(tar[j]==ori[i])j++; if(j==m){flag=1;printf("%d\n",i-m+2);return;} } } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); flag=0; for(int i=0;i<n;i++)scanf("%d",&ori[i]); for(int i=0;i<m;i++)scanf("%d",&tar[i]); getfail(tar,f); find(ori,tar,f); if(!flag){ printf("-1\n"); } } }