网站首页 > 技术文章 正文
以下是C语言实现正则表达式的代码:
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
bool isMatch(char* s, char* p) {
int m = strlen(s);
int n = strlen(p);
// 检查模式p的合法性,避免无效的'*'
for (int i = 0; i < n; ++i) {
if (p[i] == '*' && (i == 0 || p[i-1] == '*')) {
return false;
}
}
// 创建动态规划表,dp[i][j]表示s的前i个字符和p的前j个字符是否匹配
bool *dp = (bool *)calloc((m+1) * (n+1), sizeof(bool));
if (!dp) {
return false; // 内存分配失败,但题目通常保证不会出现
}
// 初始化基础情况:空字符串匹配空模式
dp[0] = true;
// 初始化第一行,处理模式p可以匹配空字符串的情况(如"a*")
for (int j = 1; j <= n; ++j) {
if (p[j-1] == '*') {
dp[j] = dp[j-2]; // 匹配0次的情况
}
}
// 填充dp表
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (p[j-1] == '*') {
// 处理'*'的情况,考虑匹配0次或多次
bool matchZero = dp[i*(n+1) + (j-2)];
bool matchMore = (p[j-2] == '.' || s[i-1] == p[j-2]) && dp[(i-1)*(n+1) + j];
dp[i*(n+1)+j] = matchZero || matchMore;
} else {
// 处理普通字符或'.'的情况
bool currentMatch = (p[j-1] == '.' || s[i-1] == p[j-1]);
dp[i*(n+1)+j] = currentMatch && dp[(i-1)*(n+1) + (j-1)];
}
}
}
bool result = dp[m*(n+1) + n];
free(dp);
return result;
}
void test(const char *s, const char *p, bool expected) {
bool result = isMatch((char*)s, (char*)p);
printf("s=\"%s\", p=\"%s\" -> %s (Expected %s)\n",
s, p,
result ? "true" : "false",
expected ? "true" : "false");
}
int main() {
// 完全匹配
test("aa", "aa", true);
// '.' 匹配任意字符
test("ab", "a.", true);
// '*' 匹配零次
test("a", "ab*", true); // b* 匹配零次
// '*' 匹配多次
test("aaa", "a*", true); // a* 匹配三次
test("ab", "a*b", true); // a* 匹配一次
// 复杂组合
test("aab", "c*a*b", true); // c* 匹配零次,a* 匹配两次
test("mississippi", "mis*is*p*.", false); // 无法匹配
// 无效模式
test("a", "a**", false); // 连续 '*' 非法
// 空字符串
test("", "", true); // 空字符串匹配空模式
test("", "a*", true); // a* 匹配零次
// 边界情况
test("a", ".*", true); // .* 匹配任意字符
return 0;
}
代码解析
- 合法性检查
确保模式 p 中的 * 不连续且不位于开头。例如 a** 或 *a 是非法的。 - 动态规划表初始化
- 使用 calloc 分配 (m+1)*(n+1) 的布尔数组,初始值为 false。
- dp[i][j] 表示 s 的前 i 个字符与 p 的前 j 个字符是否匹配。
- 基础情况
- dp[0][0] = true:空字符串与空模式匹配。
- 第一行处理模式 p 匹配空字符串的情况(例如 a* 可以匹配空)。
- 填充表格
当 p[j-1] 是 * 时:
- matchZero:匹配零次(跳过 p[j-2]),即 dp[i][j-2]。
- matchMore:匹配多次(需 p[j-2] 与 s[i-1] 匹配),即 dp[i-1][j]。
- 普通字符或 .:直接检查当前字符是否匹配,并依赖 dp[i-1][j-1]。
- 结果提取与内存释放
最终结果存储在 dp[m][n] 中,释放动态规划表内存。
算法复杂度
- 时间复杂度:O(m*n),需填充 m*n 的表格。
- 空间复杂度:O(m*n),使用一维数组模拟二维表。
- 上一篇: C语言解决荷兰国旗问题
- 下一篇: 编写第一个C++程序-HelloWorld示例
猜你喜欢
- 2025-07-21 C程序设计之:1-1/2+1/3-... + 1/n 的和
- 2025-07-21 C语言__FILE__、__LINE__等预定义跟踪调试
- 2025-07-21 C语言之核心语法(c语言核心技术第2版pdf)
- 2025-07-21 浙江男子为装修700万豪宅,买了套20万家具,收到后心都凉了
- 2025-07-21 C语言while循环要点(c语言的while循环)
- 2025-07-21 C语言-4种运算符(c语言运算符?)
- 2025-07-21 大话C语言:比较运算符(c语言比较语句)
- 2025-07-21 C语言进阶教程:数据结构-树(二叉树、平衡树)的概念与基本操作
- 2025-07-21 C语言实现“简单输出整数”,基础编程由此开始(函数篇第一节)
- 2025-07-21 C 语言技能提升:玩转运算符与表达式,提升自己的逻辑运算掌控力
- 08-03MySQL数据库的预处理详解
- 08-03《阿常·MySQL 70讲》全套教学视频
- 08-03隐式等待、显示等待和强制等待
- 08-03零基础C#上位机框架项目实例(完结篇)
- 08-03一文搞懂构建Web内容的技术
- 08-03西门子WINCC中的VBScript(VBS)常用于自动化脚本开发
- 08-03力控和sql2000之间的数据转储
- 08-03组态王|通过日历控件选择时间段查询历史报警
- 1521℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 639℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 527℃MySQL service启动脚本浅析(r12笔记第59天)
- 492℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 492℃启用MySQL查询缓存(mysql8.0查询缓存)
- 479℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 461℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 459℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- htmlbackground-image (68)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)