• HDU


    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
    ",ans);
             else puts("-1");
        }
    }
  • 相关阅读:
    Spring
    华为OJ题目:扑克牌大小
    冒泡排序算法总结
    华为OJ题目:刷题
    求立方根
    假硬币问题求解
    SQL in Qt (一)
    Qt3D教程
    (Qt 翻译) QGLAbstractScene
    (Qt 翻译) QGLSceneNode
  • 原文地址:https://www.cnblogs.com/h404nofound/p/11663692.html
Copyright © 2020-2023  润新知