HDU - 1711 A - Number Sequence(kmp
InputThe first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], ...... , a[N]. The third line contains M integers which indicate b[1], b[2], ...... , b[M]. All integers are in the range of [-1000000, 1000000].
OutputFor each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead.
Sample Input
2 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 1 3 13 5 1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 2 1
Sample Output
6 -1
题目是说给a和b数组,求b数组是否为a的连续子数组并且输出匹配的最小位置,如果找不到的话输出-1
直接暴力会超时吧(或许,读清题意后会知道这就是kmp的裸题
一开始因为用的cin交的g++超时了,然后改成scanf和c++标准过了
没啥坑,入门题,拉的满为姐姐的板子,手动模拟了一下next数组,知道了维护的东西大概明白思路了,就过了嘿嘿
然后说一下暴力做法和kmp做法,如果这道题用暴力写,也就是b数组和a数组逐个匹配,最差情况下是每次都比较到最后一个字符发现不对,知道比到最后,复杂度是O(m*n)
你已经是个成熟的acmer了,不能什么题都暴力模拟了。
kmp的写法是对数组b维护一个next数组,拿第一个样例来说,b数组是1 2 3 1 3,当匹配完第四个字符之后发现第五个不一致,但是这个时候又从头匹配的话有些浪费,然后我们发现第一个字符和第四个字符是一样的,所以可以直接跳到原第四个字符对应的位置后进行比较
1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 1 3
没有next数组时候,下一步的操作是
1 2 1 2 3 1 2 3 1 3 2 1 2 1 2 3 1 3
有的话是
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
#include<stdio.h> ///kmp算法是在线性时间内利用next数组找到tt字符串中是否出现过tt字符串 ///时间复杂度O(s+t) const int N = 1e7+5; const int M = 1e4+5; int nt[N],a[N],b[M],m,n; int kmp(int *ss,int *tt)///要匹配的是ss { int s=n; int t=m; if(s>t)return 0; nt[0]=-1; int num=0; for(int i=0,j=-1;i<s;){ if(j==-1||ss[i]==ss[j]){ i++;j++;nt[i]=j; } else j=nt[j]; }//next数组 for(int i=0,j=0;i<t;){ if(j==-1||ss[j]==tt[i]){ i++;j++; } else j=nt[j]; if(j==s){//该处表示在tt字符串中找到了ss字符串(当然你也可以在这个地方记录其他信息,我的是找到就返回1) return i+1-n; } } return 0; } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d%d",&m,&n); for(int i = 0;i < m;++i)scanf("%d",&a[i]); for(int i = 0;i < n;++i)scanf("%d",&b[i]); int ans = kmp(b,a); if(ans)printf("%d\n",ans); else puts("-1"); } }