p数组记录的是当该位置上失配的时候,跳到第几个进行继续匹配;
1 /* 2 题意:给两个数串,求模板串第一此出现在源串中的位置,开头的位置;没有输出-1; 3 算法:kmp 4 先对字符串进行自匹配; 5 然后串间匹配; 6 */ 7 #include<iostream> 8 #include<cstdio> 9 #include<cstring> 10 #include<string> 11 using namespace std; 12 int s[1000005],t[10005],p[10005];//s是源串,t是模板串,p是自匹配数组(next); 13 int n,m; 14 int kmp()//模板; 15 { 16 int ans=0; 17 p[0]=p[1]=0; 18 //p数组是错位排列的,p[i]表示的是p[i-1]的信息;即到目前为止的最长前缀; 19 for(int i=1;i<m;i++) 20 { 21 int j=p[i]; 22 while(j&&t[i]!=t[j]) 23 { 24 j=p[j];//定位j的位置; 25 } 26 p[i+1]=t[i]==t[j]?j+1:0; 27 } 28 int j=0,temp=0; 29 for(int i=0;i<n;i++) 30 { 31 while(j&&s[i]!=t[j]) 32 { 33 j=p[j]; 34 } 35 if(s[i]==t[j]) 36 j++; 37 if(j==m) 38 return i+1-m+1; 39 } 40 return 0; 41 //可以判断是否有子串,也可以计算有多少子串; 42 } 43 int main() 44 { 45 int T; 46 scanf("%d",&T); 47 while(T--) 48 { 49 memset(s,0,sizeof(s)); 50 memset(t,0,sizeof(t)); 51 scanf("%d%d",&n,&m); 52 for(int i=0;i<n;i++) 53 scanf("%d",&s[i]); 54 for(int i=0;i<m;i++) 55 { 56 scanf("%d",&t[i]); 57 } 58 int ans=kmp(); 59 if(ans==0) 60 printf("-1\n"); 61 else 62 printf("%d\n",ans); 63 } 64 return 0; 65 }