HDU - 1711 A - Number Sequence(kmp

HDU - 1711 A - Number Sequence
 
Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one.

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");
    }
}

 

posted @ 2019-10-12 20:11  小草今天又在摸鱼吗  阅读(129)  评论(0编辑  收藏  举报