数据结构实验之串三:KMP应用

本文介绍了一个使用KMP算法解决特定问题的例子。问题涉及通过给定的一组数值判断是否能唯一确定一个子序列的位置。通过C++实现的KMP算法搜索子序列,并根据搜索结果判断是否能唯一确定该子序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

有n个小朋友,每个小朋友手里有一些糖块,现在这些小朋友排成一排,编号是由1到n。现在给出m个数,能不能唯一的确定一对值l和r(l <= r),使得这m个数刚好是第l个小朋友到第r个小朋友手里的糖块数?

输入

首先输入一个整数n,代表有n个小朋友。(0

输出

 如果能唯一的确定一对l,r的值,那么输出这两个值,否则输出-1

示例输入

5
1 2 3 4 5
3
2 3 4

示例输出

2 4

提示



#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define maxsize 10000010


int next[maxsize];


using namespace std;




void getnext(int b[], int m)
{
    int i = 0, j = -1;                                  //i 用来负责遍历整个字符串s2, j 用来存放此时的最大公共长度
    next[0] = -1;                                       //当next[0]的时候不指向任何的字符串s2中的元素,就像链表中的头结点
                                                        //它用来为不满足j == -1 || s2[i] == s2[j]情况下的j 赋值
    while(i < m)
    {
        if(j == -1 || b[i] == b[j])
        {
            i++;
            j++;
            next[i] = j;
        }
        else
            j = next[j];
    }
}


int kmp(int a[], int b[], int n, int m)
{


    int i = 0, j = 0;
    getnext(b, m);                                      //调用getnext函数,来获取此时所谓的最大公共长度,也就是对应部分匹配值
                                                          //对应部分匹配值,所说就是一个字符串它的前缀和后缀中的共同元素
                                                        //当前位置的最大公共长度,就可以理解为第i个位置之前的字符串中前缀和后缀的公共长度
                                                          //例如:s2 : abcdabd   a 的前缀后缀皆为0,无公共元素
                                                           //abcd前缀为a, ab, abc 后缀为 bcd, cd, d,前缀和后缀亦无公共元素,最大公共长度亦为0
                                                             //而当abcdab的时候,前缀为a, ab, abc, abcd, abcda 后缀为 bcdab, cdab, dab, ab, a 最大公共元素为2
    while(i < n && j < m)                             //每个字符串都从第一个字符开始,直到任一字符串结束不再循环
    {
        if(j == -1 || a[i] == b[j])
        {
            i++;
            j++;
        }
        else
            j = next[j];
    }
    if(j >= m)
        return i - m + 1;
    else
        return -1;
}




int main()
{
    int n, m;
    int a[maxsize], b[maxsize];
    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];
    cin >> m;
    for(int i = 0; i < m; i++)
        cin >> b[i];
    int x = kmp(a, b, n, m);
    if(x != -1)
    {
        int y = kmp(a + x, b, n, m);
        if(y == -1)
            cout << x << " " << x + m - 1 << endl;
        else
            cout << "-1" << endl;
    }
    else
        cout << "-1" << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值