如何判断Span<T>是否按顺序包含另一个Span<T>
判断Span是否包含目标序列的解决方案
.NET标准库中没有专门用于判断Span<T>是否按顺序包含另一个完整Span<T>序列的内置方法——Span<T>.Contains仅支持检查单个元素,Overlaps仅用于判断内存区域是否重叠,确实不符合你的需求。
针对不同场景,有两种高效的处理方式:
1. 针对byte类型的Span(推荐)
如果你的Span是byte类型,.NET Core 3.0+及.NET 5+的标准库提供了MemoryExtensions.IndexOf方法,专门用于在字节Span中查找子序列,无额外内存分配且经过性能优化:
Span<byte> buffer = stackalloc byte[] { 1, 6, 2, 5, 3, 4 }; Span<byte> needle1 = stackalloc byte[] { 2, 5, 3 }; Span<byte> needle2 = stackalloc byte[] { 2, 5, 4 }; bool containsNeedle1 = buffer.IndexOf(needle1) != -1; // 返回true bool containsNeedle2 = buffer.IndexOf(needle2) != -1; // 返回false
2. 针对泛型Span
对于任意IEquatable<T>类型的Span,需要手动实现高效的序列匹配逻辑。以下是无分配的滑动窗口实现,性能接近原生操作,避免LINQ的额外开销:
public static bool ContainsSequence<T>(this Span<T> source, Span<T> target) where T : IEquatable<T> { // 边界情况处理 if (target.Length == 0) return true; if (source.Length < target.Length) return false; for (int i = 0; i <= source.Length - target.Length; i++) { bool isMatch = true; for (int j = 0; j < target.Length; j++) { if (!source[i + j].Equals(target[j])) { isMatch = false; break; } } if (isMatch) return true; } return false; }
如果需要处理超长序列,可进一步实现KMP算法,通过预构建部分匹配表减少回溯次数,提升匹配效率。
内容的提问来源于stack exchange,提问作者roten
相关产品推荐
相关产品推荐

