题解 第四章字符串| KMP方法#单词替换#

单词替换

http://www.nowcoder.com/practice/5b58a04679d5419caf62c2b238e5c9c7

法1:

复习一下KMP算法

通过KMP算法,可以轻松求出匹配的字符串的位置

可以参考如下链接:https://blog.nowcoder.net/n/82f6d123408c4d5db19cda68501d8d85

本题作了一些改变:必须要是整个的单词进行匹配才能替换,单词的前后,必须有空格

如果目标单词是大单词的一部分时,则不能够替换

再通过标记好的位置输出

另外

//采用KMP模式串匹配算法,能够更加通用得做出本题
#include <stdio.h>
#define MAX 150

//用来求KMP算法中必须的的nextval模式匹配数组
void getNextval(const char Target[], int nextval[], int Size)
{
    int i = 0, j = -1;
    int next[Size];
    next[0] = -1;
    nextval[0] = -1;
    while (i < Size)
    {
        if (j == -1 || Target[i] == Target[j])
        {
            next[++i] = ++j;
            if (Target[i] == Target[next[i]])
                nextval[i] = nextval[next[i]];
            else
                nextval[i] = next[i];
        }
        else
            j = next[j];
    }
}

//采用KMP算法
//将各次匹配成功的位置全部计入数组P中
//匹配成功后附带检验标准:
// 1若位置非零,且前一位非空格,则不算数
// 2末尾+1必须也是空格,否则不算数
//最后以-1为数组的结尾标志
void KMP_Multi(const char CArr[], const char Target[], int P[])
{
    //生成并求出目标串的nextval数组
    int Size = strlen(Target);
    int nextval[MAX] = {0};
    getNextval(Target, nextval, Size);

    int L_CArr = strlen(CArr), L_Target = strlen(Target);

    int i = 0, j = 0, R = 0;

    while (1)
    {
        while (i < L_CArr && j < L_Target)
        {
            if (j == -1 || CArr[i] == Target[j])
                i++, j++;
            else
                j = nextval[j];
        }
        if (j == L_Target)
        {
            int tmp = i - j;
            // ver1以下是从后续开始,不找包含重复的部分
            // /*
            i = i - j + L_Target;
            j = 0;
            // */
            // ver2以下是找出所有的重复部分
            /*
            i = i - j + 1;
            j = 0;
            */
            
            //以下给出了形成单词的前提要求
            if (tmp == 0 || CArr[tmp - 1] == ' ')
                if (tmp + L_Target == L_CArr || CArr[tmp + L_Target] == ' ')
                    P[R++] = tmp;
        }
        else
        {
            P[R] = -1;
            break;
        }
    }
}

int main()
{
    //下面先输入了全部数据
    char CArr[MAX] = {0}, Target[MAX] = {0}, Rep[MAX] = {0};
    //正常得获得主字符串
    fgets(CArr, MAX, stdin);
    CArr[strlen(CArr) - 1] = '\0';
    fgets(Target, MAX, stdin);
    Target[strlen(Target) - 1] = '\0';
    fgets(Rep, MAX, stdin);
    Rep[strlen(Rep) - 1] = '\0';
    //记录三个数组的长度
    int L_CArr = strlen(CArr),
        L_Target = strlen(Target),
        L_Rep = strlen(Rep);

    //采用KMP算法求出目标串各次匹配成功的位置
    //并且存入一个记录位置的数组中
    int P[MAX] = {0};
    KMP_Multi(CArr, Target, P);

    //通过记录下的断点输出结果
    if (P[0] != -1)
    {
        int i = 0, j = 0;
        for (j = 0; j < P[0]; j++)
            putchar(CArr[j]);
        while (P[++i] != -1)
        {
            printf("%s", Rep);
            for (j = P[i - 1] + L_Target; j < P[i]; j++)
                putchar(CArr[j]);
        }
        printf("%s", Rep);
        for (j = P[i - 1] + L_Target; j < L_CArr; j++)
            putchar(CArr[j]);
        putchar('\n');
    }
    else
        printf("%s\n", CArr);
    return 0;
}

将上面输出方法替换能更快得出结果

    //通过记录下的断点输出结果
    if (P[0] != -1)
    {
        int i = 0, j = 0;
        printf("%.*s",P[0],CArr); 
        while (P[++i] != -1)
        {
            printf("%s", Rep);
            printf("%.*s",P[i]-P[i-1]-L_Target,CArr+P[i-1]+L_Target); 
        }
        printf("%s", Rep);
        printf("%.*s",L_CArr-P[i-1]-L_Target,CArr+P[i-1]+L_Target); 
        putchar('\n');
    }
    else
        printf("%s\n", CArr);
    return 0;

法2:

直接替换,

逐个取出单词放到暂存数组,并进行比较和输出

#include <stdio.h>
#include <string.h>
#define MAX 150
int main()
{
    char s[MAX], a[MAX], b[MAX], tmp[MAX];
    while (fgets(s, MAX, stdin))
    {
        s[strlen(s) - 1] = '\0';
        fgets(a, MAX, stdin);
        a[strlen(a) - 1] = '\0';
        fgets(b, MAX, stdin);
        b[strlen(b) - 1] = '\0';

        for (int i = 0; i < strlen(s); i++)
        {
            int k = 0;
            while (s[i] != ' ' && s[i] != '\0')
                tmp[k++] = s[i++]; //当非空时,逐步将s字符串读入tmp
            tmp[k] = '\0';         //将读入的tmp与要替换的单词作比较
            if (strcmp(tmp, a) == 0)
                printf("%s ", b); //如果某一单词不同,输入替换的b
            else
                printf("%s ", tmp);
        }
    }
}

王道机试指南刷题 文章被收录于专栏

计划刷完这本书

全部评论

相关推荐

3 收藏 评论
分享
牛客网
牛客企业服务