C语言判断字符串是否为另一个字符串的子串

在C语言中,判断一个字符串是否为另一个字符串的子串可以通过多种方法实现。下面简要介绍两种常见的方法:暴力匹配和KMP算法。

1. 暴力匹配(Brute Force)

暴力匹配是一种简单直观的方法,它逐个字符地在主串中寻找子串的出现位置。

实现步骤:

  • 遍历主串中每个可能的起始位置。
  • 对于每个起始位置,逐个字符比较主串和子串中的字符。
  • 如果完全匹配,返回子串在主串中的起始位置;否则,继续检查下一个位置。

示例代码:

c
#include <stdio.h> #include <string.h> int isSubstring(char *mainStr, char *subStr) { int mainLen = strlen(mainStr); int subLen = strlen(subStr); for (int i = 0; i <= mainLen - subLen; ++i) { int j; for (j = 0; j < subLen; ++j) { if (mainStr[i + j] != subStr[j]) break; } if (j == subLen) // 子串完全匹配 return i; } return -1; // 没有找到子串 } int main() { char mainStr[] = "Hello, World!"; char subStr[] = "World"; int pos = isSubstring(mainStr, subStr); if (pos != -1) printf("子串 \"%s\" 在主串 \"%s\" 中的位置是:%d\n", subStr, mainStr, pos); else printf("子串 \"%s\" 不是主串 \"%s\" 的子串\n", subStr, mainStr); return 0; }

2. KMP算法

KMP算法利用了前缀函数(Partial Match Table)来优化匹配过程,能够在O(m+n)的时间复杂度内完成匹配,其中m和n分别是主串和子串的长度。

实现步骤:

  • 构建子串的前缀函数(部分匹配表)。
  • 利用前缀函数进行匹配,避免不必要的回溯。

示例代码:

c
#include <stdio.h> #include <string.h> void computeLPSArray(char *subStr, int subLen, int *lps) { int len = 0; // 最长匹配前缀的长度 lps[0] = 0; // 第一个字符的前缀长度总是0 int i = 1; while (i < subLen) { if (subStr[i] == subStr[len]) { len++; lps[i] = len; i++; } else { if (len != 0) len = lps[len - 1]; else { lps[i] = 0; i++; } } } } int KMPSearch(char *mainStr, char *subStr) { int mainLen = strlen(mainStr); int subLen = strlen(subStr); int lps[subLen]; // 用于存储部分匹配表(最长匹配前缀长度) computeLPSArray(subStr, subLen, lps); int i = 0; // 主串索引 int j = 0; // 子串索引 while (i < mainLen) { if (subStr[j] == mainStr[i]) { j++; i++; } if (j == subLen) { return i - j; // 找到子串在主串中的位置 j = lps[j - 1]; } else if (i < mainLen && subStr[j] != mainStr[i]) { if (j != 0) j = lps[j - 1]; else i++; } } return -1; // 没有找到子串 } int main() { char mainStr[] = "Hello, World!"; char subStr[] = "World"; int pos = KMPSearch(mainStr, subStr); if (pos != -1) printf("子串 \"%s\" 在主串 \"%s\" 中的位置是:%d\n", subStr, mainStr, pos); else printf("子串 \"%s\" 不是主串 \"%s\" 的子串\n", subStr, mainStr); return 0; }

这两种方法各有优劣,暴力匹配简单直观但效率较低,适用于较短的字符串;而KMP算法则更适合处理较长的字符串,通过前缀函数实现了时间复杂度的优化。选择合适的方法取决于具体的应用场景和数据量大小。