KMP拓展(CCPC网络 A Secret)&&HDU4300

关于KMP的拓展,其实我感觉过程有点类似
能理解KMP之前的next数组更好,不理解也可以看
图文并茂:
大佬的讲解

HDU 4300

这道题的题意窝看了好几篇博客才看懂,然后看懂也做不粗来。。。。。
这里说一下吧。

题意:

给两个字符串,第一行字符串是作为密文的字典,第二行就可能是密文+明文(明文可能没有)然后将密文转为明文,即输出格式为:密文+明文(这里的明文就是密文翻译过来的),尽可能少的添加字母并使密文与明文一一对应。
还是举个栗子吧:
qwertyuiopasdfghjklzxcvbnm
qwertabcde

这里第一行的qwert就代表着“abcde”(后面的以此类推),第二行如果将qwert看做密文,就需要翻译成abcde
这时候会发现“qwert”后面刚好就是我们所需要的“abcde”这样就不用去添加字母了,那么这个假设就成为了我们的最优解

思路:

因为密文一定存在,则将密文翻译成明文之后的长度就是原有密文长度的两倍,即密文在所给的字符串中至少占有
一半。所以直接用map映射第二行的字符串,然后作为模式串与第二行字符串(即文本串)求出extend数组(extend数组存放的值代表从第i位开始到末端与文本串相同的前缀)

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<map>
#pragma warning (disable :4996)
using namespace std;
#define maxn 100010
/* 求解T中next[],注释参考GetExtend() */
void GetNext(char* T, int nex[])
{
    int t_len = strlen(T);
    nex[0] = t_len;
    int a;
    int p;

    for (int i = 1, j = -1; i < t_len; i++, j--)
    {
        if (j < 0 || i + nex[i - a] >= p)
        {
            if (j < 0)
                p = i, j = 0;

            while (p < t_len&&T[p] == T[j])
                p++, j++;

            nex[i] = j;
            a = i;
        }
        else
            nex[i] = nex[i - a];
    }
}

/* 求解extend[] */
void GetExtend(char* S, char*T, int extend[], int next[])
{
    GetNext(T, next);  //得到next
    int a;
    int p;             //记录匹配成功的字符的最远位置p,及起始位置a
    int s_len = strlen(S);
    int t_len = strlen(T);

    for (int i = 0, j = -1; i < s_len; i++, j--)  //j即等于p与i的距离,其作用是判断i是否大于p
                                                //(如果j<0,则i大于p)
    {
        if (j < 0 || i + next[i - a] >= p)  //i大于p(其实j最小只可以到-1,j<0的写法方便读者理解程序),
        {                                   //或者可以继续比较(之所以使用大于等于而不用等于也是为了方便读者理解程序)
            if (j < 0)
                p = i, j = 0;  //如果i大于p ,p为从i开始匹配成功的最远距离

            while (p < s_len&&j < t_len&&S[p] == T[j])
                p++, j++;

            extend[i] = j;
            a = i; //起始位置
        }
        else
            extend[i] = next[i - a];
    }
}
map<char, char>q;
int main()
{
    int nex[maxn] = { 0 };
    int extend[maxn] = { 0 };
    char a[maxn], b[maxn], c[maxn];
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s%s", &a, &b);
        int len = strlen(a);
        int len1 = strlen(b);
        for (int i = 0; i < len; i++)
            q[a[i]] = 'a' + i; //映射后存入map
        for (int i = 0; i < len1; i++)
            c[i] = q[b[i]];//映射
        c[len1] = '\0';
        GetExtend(b, c, extend, nex);
        /*for (int i = 0; i < len; i++)cout << extend[i]<<' ';
        cout << endl;*/
        int k;
        for (k = 0; k <len1; k++) {
            if (k + extend[k] >= len1 && k >= extend[k])//k代表密文长度
                break;
        }

        for (int i = 0; i <k; i++)cout << b[i];
        for (int i = 0; i <k; i++)cout << q[b[i]];
        cout << endl;
    }
    return 0;
}

CCPC网络赛
A Secret

思路:

因为题目原本是要找后缀。
但是kmp拓展是关于前缀的,所以将字符串翻转。
再由extend数组的等差之和(取模后),则为所求答案

然后直接贴代码吧。代码是直接搬运的没多少改动 ̄□ ̄||

#pragma warning (disable :4996);
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
const ll mod = 1000000007LL;
char s[N], t[N];
int ne[N], extend[N];

void getnxt(char T[], int len, int nxt[]){
    nxt[0] = len;
    int a;
    int p;
    for (int i = 1, j = -1; i < len; i++, j--){
        if (j < 0 || i + nxt[i - a] >= p){
            if (j < 0)
                p = i, j = 0;
            while (p < len && T[p] == T[j])
                p++, j++;
            nxt[i] = j;
            a = i;
        }
        else
            nxt[i] = nxt[i - a];
    }
}
void getextend(char S[], char T[], int ls, int lt, int extend[], int nxt[])
{
    getnxt(T, lt, nxt);  //得到next
    int a;
    int p;             //记录匹配成功的字符的最远位置p,及起始位置a
    for (int i = 0, j = -1; i < ls; i++, j--)  //j即等于p与i的距离,其作用是判断i是否大于p(如果j<0,则i大于p)
    {
        if (j < 0 || i + nxt[i - a] >= p)  //i大于p(其实j最小只可以到-1,j<0的写法方便读者理解程序),
        {   //或者可以继续比较(之所以使用大于等于而不用等于也是为了方便读者理解程序)
            if (j < 0)
                p = i, j = 0;  //如果i大于p
            while (p < ls && j < lt && S[p] == T[j])
                p++, j++;
            extend[i] = j;
            a = i;
        }
        else
            extend[i] = nxt[i - a];
    }
}
int main(void)
{
    int T, i;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%s%s", s, t);
        int la = strlen(s);
        int lb = strlen(t);
        //翻转
        reverse(s, s + la);
        reverse(t, t + lb);
        getnxt(t, lb, ne); //获取next 数组在下一函数做实参
        getextend(s, t, la, lb, extend, ne);
        ll ans = 0;
        for (i = 0; i < la; ++i)
        {
            ll temp = (ll)extend[i] * ((ll)extend[i] + 1) / 2;//等差求结果
            ans = (ans + temp) % mod;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值