C语言练习百题之计算字符串中子串出现的次数

ops/2024/9/25 15:24:52/

程序分析

计算字符串中子串出现的次数,一种直观的方法是遍历整个字符串,在每个位置检查子串是否匹配。另一种方法是利用字符串匹配算法来优化搜索过程,减少时间复杂度。

方法一:暴力法

解题思路

  • 在主串中依次遍历每个位置,以该位置为起点,检查是否存在与子串相同的子串。
  • 比较简单直观,但时间复杂度较高。

实现代码

#include <stdio.h>
#include <string.h>int countSubstring(char *str, char *sub) {int count = 0;int len_str = strlen(str);int len_sub = strlen(sub);for (int i = 0; i <= len_str - len_sub; i++) {int j;for (j = 0; j < len_sub; j++) {if (str[i + j] != sub[j])break;}if (j == len_sub)count++;}return count;
}int main() {char str[] = "ababababa";char sub[] = "aba";int result = countSubstring(str, sub);printf("Number of occurrences: %d\n", result);return 0;
}

优缺点

  • 优点:实现简单,容易理解。
  • 缺点:时间复杂度高,O(n*m),其中n为主串长度,m为子串长度。

方法二:KMP算法

解题思路

  • KMP算法利用了子串内部的信息,通过预处理生成一个部分匹配表,然后根据部分匹配表进行匹配,减少了不必要的比较。
  • 预处理过程时间复杂度为O(m),匹配过程时间复杂度为O(n+m),总体时间复杂度为O(n+m),其中n为主串长度,m为子串长度。

实现代码

#include <stdio.h>
#include <string.h>void buildTable(char *sub, int *table) {int len = strlen(sub);table[0] = 0;int j = 0;for (int i = 1; i < len; i++) {while (j > 0 && sub[i] != sub[j])j = table[j - 1];if (sub[i] == sub[j])j++;table[i] = j;}
}int countSubstringKMP(char *str, char *sub) {int count = 0;int len_str = strlen(str);int len_sub = strlen(sub);int table[len_sub];buildTable(sub, table);int j = 0;for (int i = 0; i < len_str; i++) {while (j > 0 && str[i] != sub[j])j = table[j - 1];if (str[i] == sub[j])j++;if (j == len_sub) {count++;j = table[j - 1];}}return count;
}int main() {char str[] = "ababababa";char sub[] = "aba";int result = countSubstringKMP(str, sub);printf("Number of occurrences: %d\n", result);return 0;
}

优缺点

  • 优点:时间复杂度较低,O(n+m),其中n为主串长度,m为子串长度。
  • 缺点:实现相对复杂,需要了解和实现KMP算法

方法三:Boyer-Moore算法

解题思路

  • Boyer-Moore算法也是一种字符串匹配算法,其核心思想是从后往前匹配,并利用坏字符和好后缀规则进行跳跃。
  • 时间复杂度为O(n/m),其中n为主串长度,m为子串长度。

实现代码(Boyer-Moore算法的实现相对复杂,这里不做展示)。

优缺点

  • 优点:性能较好,适用于长主串和短子串的情况。
  • 缺点:实现复杂,需要深入理解算法原理。

总结

  • 如果字符串规模较小,且不涉及大量匹配操作,暴力法是一个简单直观的选择。
  • 如果需要处理大规模字符串,特别是当子串较短时,推荐使用KMP算法或者Boyer-Moore算法,它们可以显著提高匹配效率。
  • 在KMP算法和Boyer-Moore算法中,Boyer-Moore算法在实际应用中可能更优,但需要付出更多的实现成本。

http://www.ppmy.cn/ops/35750.html

相关文章

云原生周刊:Terraform 1.8 发布 | 2024.5.6

开源项目推荐 xlskubectl 用于控制 Kubernetes 集群的电子表格。xlskubectl 将 Google Spreadsheet 与 Kubernetes 集成。你可以通过用于跟踪费用的同一电子表格来管理集群。 git-sync git-sync 是一个简单的命令&#xff0c;它将 git 存储库拉入本地目录&#xff0c;等待一…

运行容器时发现内存不足(<2G)--docker版本低:重装docker

一、卸载&#xff1a; sudo yum install -y yum-utilssudo yum remove docker-ce docker-ce-cli containerd.iosudo rm -rf /var/lib/dockersudo rm -rf /var/lib/containerd 二、安装&#xff1a; sudo yum-config-manager --add-repo https://download.docker.com/linux/ce…

linux上Redis安装使用

环境centOS8 redis是缓存数据库&#xff0c;主要是用于在内存中存储数据&#xff0c;内存的读写很快&#xff0c;加快系统读写数据库的速度 一、Linux 安装 Redis 1. 下载Redis 官网下载Downloads - Redis 历史版本Index of /releases/ 本文中安装的版本为&#xff1a;h…

百度语音识别开发笔记

目录 简述 开发环境 1、按照官方文档步骤开通短语音识别-普通话 2、创建应用 3、下载SDK 4、SDK集成 5、相关接口简单说明 5.1权限和key 5.2初始化 5.3注册回调消息 5.4开始转换 5.5停止转换 6、问题 简述 最近想做一些语音识别的应用&#xff0c;对比了几个大厂…

杰发科技AC7801——支持的纠错功能

1. 复位寄存器保留复位类型 低压检测复位&#xff08;LVD Reset&#xff09; 集成了一个低压保护系统&#xff0c;以便在电源电压发生变化期间保护存储器内容和控制 MCU 系统状态。该系统由上电复位(POR)电路和 LVD 电路组成&#xff0c;LVD 可以配置为不同的复位基准&#x…

ComfyUI 基础教程(十三):ComfyUI-Impact-Pack 面部修复

SD的WebUI 中的面部修复神器 ADetailer,无法在ComfyUI 中使用。那么如何在ComfyUI中进行面部处理呢?ComfyUI 中也有几个面部修复功能,比如ComfyUI Impact Pack(FaceDetailer),以及换脸插件Reactor和IPAdapter。 ComfyUI-Impact-Pack 是一个功能强大的插件,专为 ComfyUI …

Node.js及其生态:分享Node.js的基础知识,包括调试,流,模块等。同时也可以介绍一些流行框架如Express,Koa,NestJS等

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞 I/O 模型&#xff0c;使其轻量又高效。Node.js 的包生态系统&#xff08;npm&#xff09;是全球最大的开源库生态系统。 一些基础概念&#xff1a; 调试&#xff1a;你可以使用…

202003青少年软件编程(Python)等级考试试卷(二级)

第 1 题 【单选题】 运行下方代码段,输出的结果是(   )。 a=(1,2,3)print(type(a))A :<class ‘float’> B :<class ‘int’> C :<class ‘str’> D :<class ‘tuple’> 正确答案:D 试题解析: 第 2 题 【单选题】 content.txt中原来的内容…