C语言中多维数组特定0模式匹配的高效算法求解
高效0-1矩阵模式匹配算法(仅匹配pattern中的0)
核心匹配规则
先明确需求边界:
- 仅当pattern的行数
P_rows ≤ M_rows且列数P_cols ≤ M_cols时执行匹配(若要求严格小于,只需调整坐标范围为x ∈ [0, M_rows-P_rows)、y ∈ [0, M_cols-P_cols)) - 匹配成功条件:match中任意
P_rows×P_cols的子矩阵,所有对应pattern为0的位置必须是0;pattern为1的位置,子矩阵对应元素可0可1,不影响匹配
针对超大矩阵(1e6×1e6)的高效方案
由于1e6×1e6的矩阵无法直接存储完整前缀和(内存需求达数TB),必须选择低内存、高效率的算法,以下两种方案按需选择:
方案1:禁止位置标记法(优先推荐,适配稀疏/稠密矩阵)
思路
匹配失败的子矩阵,必然是其覆盖范围内存在某个1的位置,正好对应pattern中的0位置。我们只需找出所有这类无效子矩阵,用总候选数减去无效数即可得到匹配数。
步骤
- 计算总候选数:若
P_rows > M_rows或P_cols > M_cols,直接返回0;否则总候选数total = (M_rows - P_rows + 1) * (M_cols - P_cols + 1) - 提取pattern的0位置:记录所有
(dx, dy),其中pattern[dx][dy] == 0(记为集合zero_pos)。若zero_pos为空,说明pattern全是1,所有候选子矩阵都匹配,直接返回total - 收集match的1位置:遍历match矩阵,记录所有
(a, b),其中match[a][b] == 1(记为集合ones) - 标记无效子矩阵:
- 对每个1的位置
(a, b),遍历zero_pos中的每个(dx, dy) - 计算无效子矩阵的左上角坐标
x = a - dx,y = b - dy - 若
x在[0, M_rows-P_rows]范围内,且y在[0, M_cols-P_cols]范围内,将(x, y)加入无效集合(用哈希集合或位图分块去重)
- 对每个1的位置
- 计算匹配数:
match_count = total - len(无效集合)
优势
- 内存占用极低:无需存储完整match矩阵或前缀和,仅需存储稀疏的1位置和无效子矩阵位置
- 效率可控:match中1越少,算法越快;即使1较多,位图分块也能高效存储无效位置
方案2:流式滑动窗口法(适配pattern较小的场景)
若pattern的行数P_rows较小(如≤1000),可采用流式处理,避免存储完整match矩阵:
步骤
- 预处理pattern行信息:对pattern的每一行,记录该行中0的列索引集合
row_zero[dx](dx为行号) - 流式处理match行:
- 维护一个大小为
P_rows的窗口,存储最近P_rows行的列滑动窗口求和结果 - 对每一行
i,计算该行每个列起始位置y的求和值:row_sum[y] = sum(match[i][y+dy] for dy in row_zero[dx]),其中dx是当前行在窗口中的相对行号
- 维护一个大小为
- 列滑动窗口校验:对每个列起始位置
y,维护最近P_rows行的row_sum[y]之和,若总和为0,说明该子矩阵匹配成功,计数加1
优势
- 流式处理,无需存储完整match矩阵,内存占用仅为
O(P_rows * M_cols) - 适合pattern较小、match为稠密矩阵的场景
示例验证
用你给出的示例:
- pattern的
zero_pos = {(0,0), (1,0), (1,1)} - match的1位置为
(0,1), (0,3), (2,0), (2,4) - 总候选数
total = (3-2+1)*(5-2+1) = 8 - 标记的无效子矩阵为
(0,1), (0,3), (1,0), (1,3),共4个 - 匹配数
8-4=4,与示例结果一致
内容的提问来源于stack exchange,提问作者DirtyV
相关产品推荐
相关产品推荐

