C - Number Sequence - KMP

本文解析了如何使用KMP算法解决题目中的数列匹配问题,通过构建next数组求解子数组首元素的最小匹配位置。注意处理数组从1开始的下标问题。实例演示了如何在给定数组a和b中找到最长连续子数组使得它们对应相等。
摘要由CSDN通过智能技术生成

C - Number Sequence - KMP

题干

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

知识点&算法

题意就是给数组a,b,让我们在a中找能够匹配b的子数组,并取所有子数组中首元素下标最小的一个并返回首元素下标。
虽然不是字符串,也可以用KMP来做。还就那个求一手nex数组然后匹配即可。
特别要注意的是,题干所给的数组下标是从1开始的,所以最后打印答案时要额外+1

题解

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
int a[1000005],b[10005],nex[10005];
int n,m,ans,l,r;

int main()
{
    int __;
    cin>>__;
    while(__--){
        cin>>n>>m;
        for(int i = 0 ; i < n ; ++i) scanf("%d",a+i);
        for(int j = 0 ; j < m ; ++j) scanf("%d",b+j);
        memset(nex,0,sizeof(nex));
        nex[0] = -1;
        l = -1, r = 0;
        while(r <= m){
            if(l == -1 || b[l] == b[r]){
                nex[++r] = ++l;
            }else l = nex[l];
        }
        l = 0;
        r = 0;
        while(l < n && r < m){
            if(r == -1 || a[l] == b[r]){
                l++;
                r++;
            }else r = nex[r];
        }
        if(r >= m) cout<<l - m + 1<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值