2月10日总结--kmp

题目描述

给出两个字符串 s_1s1​ 和 s_2s2​,若 s_1s1​ 的区间 [l, r][l,r] 子串与 s_2s2​ 完全相同,则称 s_2s2​ 在 s_1s1​ 中出现了,其出现位置为 ll。
现在请你求出 s_2s2​ 在 s_1s1​ 中所有出现的位置。

定义一个字符串 ss 的 border 为 ss 的一个非 ss 本身的子串 tt,满足 tt 既是 ss 的前缀,又是 ss 的后缀。
对于 s_2s2​,你还需要求出对于其每个前缀 s's′ 的最长 border t't′ 的长度。

输入格式

第一行为一个字符串,即为 s_1s1​。
第二行为一个字符串,即为 s_2s2​。

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 s_2s2​ 在 s_1s1​ 中出现的位置。
最后一行输出 |s_2|∣s2​∣ 个整数,第 ii 个整数表示 s_2s2​ 的长度为 ii 的前缀的最长 border 长度。

输入输出样例

输入 #1复制

ABABABC
ABA

输出 #1复制

1
3
0 0 1 

#include<stdio.h>
#include<string.h>
long long int next[1000005]= {0},vis[1000005];//记录最大相同前后缀的长度
char a[1000005],b[1000005];
long long int lena,lenb;
void nn(char t[],long long int next[])//记录不相等时j指针要跳回的位置
{
    int i;
    int j;
    next[0]=-1;
    i=0,j=-1;
    while(i<strlen(t))
    {
        if(j==-1||t[i]==t[j])
        {
            i++;
            j++;
            vis[i]=j;
            if(t[i]==t[j])
                next[i]=next[j];
            else
                next[i]=j;
        }
        else
            j=next[j];
    }
}
void cmp(char a[],char b[])//!!!自定义函数无返回值要用void,用int会运行错误
{
    nn(b,next);
    int j=0,i=0;

    while(i<lena)
    {
        if(j==-1||a[i]==b[j])
        {
            j++;
            i++;

        }
        else
            j=next[j];
        //printf("i=%d j=%d\n",i,j);
        if(j>=lenb)
        {
            printf("%d\n",i-lenb+1);
            j=next[j];
        }
    }
}
int main()
{
    scanf("%s",a);
    scanf("%s",b);
    lena=strlen(a),lenb=strlen(b);
    //printf("len=%d\n",lena);
    cmp(a,b);
    for(int i=1; i<=lenb; i++)
        printf("%d ",vis[i]);
}


 

总结:kmp挺抽象的,今天发现编译器上只能复制四千多个字符

奶牛们非常享受在牛栏中哞叫,因为她们可以听到她们哞声的回音。虽然有时候并不能完全听到完整的回音。Bessie曾经是一个出色的秘书,所以她精确地纪录了所有的哞叫声及其回声。她很好奇到底两个声音的重复部份有多长。

输入两个字符串(长度为1到80个字母),表示两个哞叫声。你要确定最长的重复部份的长度。两个字符串的重复部份指的是同时是一个字符串的前缀和另一个字符串的后缀的字符串。

我们通过一个例子来理解题目。考虑下面的两个哞声:

moyooyoxyzooo

yzoooqyasdfljkamo

第一个串的最后的部份"yzooo"跟第二个串的第一部份重复。第二个串的最后的部份"mo"跟第一个串的第一部份重复。所以"yzooo"跟"mo"都是这2个串的重复部份。其中,"yzooo"比较长,所以最长的重复部份的长度就是5。

输入格式

* Lines 1..2: Each line has the text of a moo or its echo

输出格式

* Line 1: A single line with a single integer that is the length of the longest overlap between the front of one string and end of the other.

输入输出样例

输入 #1复制

abcxxxxabcxabcd 
abcdxabcxxxxabcx 

输出 #1复制

11 

说明/提示

 

#include<stdio.h>
#include<string.h>

long long int next[1000005]= {0};
char a[1000005],b[1000005];
long long int lena,lenb;

void nn(char t[],long long int next[])
{
    int i;
    int j;
    next[0]=-1;
    i=0,j=-1;
    while(i<strlen(t))
    {
        if(j==-1||t[i]==t[j])
        {
            i++;
            j++;

                next[i]=j;
        }
        else
            j=next[j];
    }
}
int cmp(char a[],char b[],int lena)
{
    nn(b,next);
    int j=0,i=0;

    while(i<lena)
    {
        if(j==-1||a[i]==b[j])
        {
            j++;
            i++;

        }
        else
            j=next[j];
        //printf("i=%d j=%d\n",i,j);
    }
    return j;

}
int max(int a,int b)
{
    if(a>b)
        return a;
    else
        return b;
}
int main()
{
    scanf("%s",a);
    scanf("%s",b);
    lena=strlen(a),lenb=strlen(b);
    //printf("len=%d\n",lena);

    printf("%d",max(cmp(a,b,lena),cmp(b,a,lenb)));

}
 

 

思路:利用kmp,将第二串和第一串进行比对,直到比对到第一串的最后一个字符,如果相等,就说明最大长度就是第二串比对到的位置,如果不是,就回溯

明日计划:学一下二维数组在函数中的调用,了解一下map的用法 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值