【PTA数据结构 | C语言版】字符串匹配算法比较

发布于:2025-07-15 ⋅ 阅读:(15) ⋅ 点赞:(0)

本专栏持续输出数据结构题目集,欢迎订阅。

文章目录

题目

给定两个由英文字母组成的字符串 string 和 pattern,要求找到 pattern 在 string 中第一次出现的位置,并将此位置后的 string 的子串输出。如果找不到,则输出“Not Found”。

本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:

  • 数据0:小规模字符串,测试基本正确性;
  • 数据1:随机数据,String 长度为 10^5,Pattern 长度为 10;
  • 数据2:随机数据,String 长度为 10^5,Pattern 长度为 10^2;
  • 数据3:随机数据,String 长度为 10^5,Pattern 长度为 10^3;
  • 数据4:随机数据,String 长度为 10^5,Pattern 长度为 10^4;
  • 数据5:String 长度为 10^6,Pattern 长度为 10^5;测试尾字符不匹配的情形;
  • 数据6:String 长度为 10^6 ,Pattern 长度为 10^5;测试首字符不匹配的情形。

输入格式:
输入第一行给出 string,为由英文字母组成的、长度不超过 10^6 的字符串。第二行给出一个正整数 n(≤10),为待匹配的模式串的个数。随后 n 行,每行给出一个 pattern,为由英文字母组成的、长度不超过 10^5 的字符串。每个字符串都非空,以回车结束。

输出格式:
对每个 pattern,按照题面要求输出匹配结果。

输入样例:
abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz

输出样例:
abcabcacabxy
Not Found
Not Found

代码

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

int la, lb;                 // 主串和模式串的长度
int next[1000001];          // KMP算法的next数组
char a[1000001], b[1000001]; // 主串和模式串(下标从1开始)

// 计算模式串的next数组(部分匹配表)
void Next() {
    int i, j = 0;
    for (i = 2; i <= lb; i++) {
        // 不匹配时回溯到上一个可能位置
        while (j > 0 && b[i] != b[j + 1]) {
            j = next[j];
        }
        if (b[i] == b[j + 1])
            j++;
        next[i] = j;
    }
}

// KMP算法实现:在主串a中查找模式串b的首次出现
int KMP(char a[], char b[]) {
    int j = 0, t = 0, l = -1; // l=-1表示未找到匹配
    for (int i = 1; i <= la; i++) {
        // 不匹配时回溯到next数组指示的位置
        while (j > 0 && b[j + 1] != a[i]) {
            j = next[j];
        }
        if (b[j + 1] == a[i])
            j++;
        // 找到完整匹配
        if (j == lb) {
            t = i - lb + 1; // 记录匹配起始位置
            l = 0;          // 标记已找到
            break;
        }
    }
    // 输出匹配位置后的子串
    if (l == 0) {
        for (; t <= la; t++) {
            printf("%c", a[t]);
        }
    }
    return l; // 返回是否找到的标志
}

int main() {
    scanf("%s", a + 1);       // 主串从下标1开始存储
    la = strlen(a + 1);       // 计算主串长度
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%s", b + 1);   // 模式串从下标1开始存储
        lb = strlen(b + 1);   // 计算模式串长度
        Next();               // 预处理next数组
        int m = KMP(a, b);    // 执行KMP匹配
        if (m == -1)
            printf("Not Found");
        if (i != n - 1)       // 最后一个结果后不输出额外换行
            printf("\n");
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到