.NET源码学习 [算法2-数组与字符串的查找与匹配]( 四 )


先简单介绍一下类型Span<T>

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
该类型被微软官方称为“新增的重要组成部分“ , 其主要作用是提供任意内存连续区域的类型安全与内存安全表示形式 。即 , 此数据类型可以实现对任意内存的相邻区域进行操作 , 无论相应内存是与托管对象相关联 , 还是通过互操作由本机代码提供 , 亦或是位于堆栈上 。解决了在不使用不安全代码(指针等直接对内存进行的操作)的情况下 , 实现了在内存上 , 对数据进行修改的操作 。更多详细信息请参阅(C# - Span 全面介绍:探索 .NET 新增的重要组成部分 | Microsoft Docs) 。
ReadOnlySpan<T>亦是如此 , 只是被附上了对内部元素只读的属性 , 以满足字符串不可修改的基本性质 。
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
其将传入的字符串首字符作为指针的起始位置 , length为字符串的长度 , 通过指针+偏移量的方式(类似于C++中通过指针ptr访问数组第一个位置 , ptr++实现向后偏移) , 实现对数据的访问 。
5. 九个构造方法
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
与其他类型的构造方法不同 , 这九个构造方法均为外部方法extern , 需要从外部从新定义其实现形式 。个人猜测 , 外部定义可能在.NET库中 。其功能均是将所给数据集 , 按照一定条件转化为字符串 。详细信息参考下表:
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
(三) 有关String的查找与匹配1. BF算法(Brute Force)Brute Force , 一种暴力匹配算法 , 其思想是对于两个字符串 s 与  , 在s(主串)中查找/匹配pat(模式串) 。若s[i] == pat[j] , 则i++且j++;否则i++且j = 0 。此时 i 即为模式串 pat 在主串 s 中第一次匹配的起始下标位置 。
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
复杂度分析:
  • 时间复杂度:O( nm )(最快O( n+ m ) , pat 在 s 的开头就匹配完成;最慢O( nm ) , 每次都是在 pat 的末尾匹配失败)
  • 空间复杂度:O( 1 )
我们找个题目测试一下其运行效率(题目:kmp算法_牛客题霸_牛客网 (nowcoder.com))
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图

.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
实测运行时间:
【注:由于牛客上的本题无法获取该超时样例 , 因此此处及之后选用某一衰减测试样例进行实测计时 , 仅用于观察算法时间复杂度 。样例:主串字符全为 ‘A’ , 长度为500000;模式串字符全为 ‘A’ , 长度为100】
.NET源码学习 [算法2-数组与字符串的查找与匹配]

文章插图
毫无疑问 , 对于这样的时间复杂度 ,  105 及以上量级的数据是比较慢的 。虽然理论上BF算法时间复杂度较高 , 但其在实际开发中比较常用原因主要有以下2点:

经验总结扩展阅读