zoukankan      html  css  js  c++  java
  • 【2018.07.27】(字符串/找相同)学习KMP算法小记

    虽然说原理很好理解,但是代码理解了花费我一个下午的时间,脑阔痛

    该注释的地方都标记了,希望以后看到这些代码我还能好好理解吧

    学习的链接地址:https://www.cnblogs.com/teble/p/7280575.html

    /*     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. 
    Input
    The 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]. 
    Output
    For 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*/
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define MAXN 1000050
    using namespace std;
    //这道题看得出来需要使用到KMP排序
    //虽然说我理解了排序原理,却不太懂得实现它 
    //对于我这种来说,最担心的的莫过于输入问题(所以最后干脆用int数组解决) 
    int a[MAXN], b[10050], _next[10050];
    int repeat, i, n;
    __int64 m;
    
    void makeNext()
    {
        int q=1;//模板b字符串的临时下标,作为比较的后一位 
        int k=0;//最大前后缀长度
        _next[1]=0;//模板字符串第一个字符最大前后缀长度为0 
        while ( q<n )//遍历数组 
        {
            if ( k==0 || b[k]==b[q] )//符合条件 
            {
                ++k,++q;//同时+1,判断下一位 
                if ( b[q]!=b[k] ) _next[q]=k;
                    else _next[q]=_next[k];//上下两句话改变next数组的值 
            } else k=_next[k];//如果不相等,将前标往前移动 
        } 
        /*数据检查for ( k=1 ; k<=n ; k++ )
        {
            cout<<b[k]<<' ';
        }
        cout<<endl;
        for ( k=1 ; k<=n ; k++ )
        {
            cout<<_next[k]<<' ';
        }
        cout<<endl;*/
    }
    
    int kmp()
    {
        int i, j;
        for ( i=1,j=1 ; i<=m&&j<=n ; )
        {
            if ( j==0 || a[i]==b[j] ) ++i,++j;
                else j=_next[j];//如果不相等的话,将此时的j变小,相当于将b数组往右移动 
                //next数组提供,当a[]的后m个元素和b[]开头的前m个元素顺序相同时提供下标的服务 
        }
        if ( j==n+1 ) return i-n;//i是当前点,n是b[]的长度,返回的是初始点 
            else return -1;//j==n+1的原因是a[]都被遍历完了,而b[]仍未遍历完
            //只有当b[]都被遍历完了才算完整结束 
    }
    
    
    int main(void)
    {
        scanf("%d", &repeat);
        while ( repeat-- )
        {
            scanf("%I64d%d",&m ,&n);
            for ( i=1 ; i<=m ; i++ )
            {
                scanf("%d", &a[i]);
            }
            for ( i=1 ; i<=n ; i++ )
            {
                scanf("%d", &b[i]);
            }
            makeNext();
            cout<<kmp()<<endl;
        }
        return 0;
    }
  • 相关阅读:
    二元查找树的后序遍历结果
    CFileDialog设置多选时的一个问题
    KanRSS.com
    由shuttle这个单词想起的一个小故事
    Sun Java moved to the Partner repository
    Sun Java moved to the Partner repository
    扩展std::string功能的几个做法
    NetBeans 时事通讯(刊号 # 99 Apr 16, 2010)
    NetBeans IDE 6.9 Beta 发布
    KanRSS.com
  • 原文地址:https://www.cnblogs.com/mokou/p/9378543.html
Copyright © 2011-2022 走看看