Python:数据流中查找特定子串的简单算法
来源:互联网 发布:数据库三大范式的例题 编辑:程序博客网 时间:2024/04/29 20:58
Python:数据流中查找特定子串的简单算法
目录
- 1问题背景
- 2定义:什么是数据流?
- 3原始方法
- 4学术上的标准方法
- 5实用的简单算法
问题背景
HTTP的服务器响应包括响应头部(headers)和body。两者的分割标记是连续的2个\r\n,即\r\n\r\n 4字节的序列。现在的问题是,编写一个简单的算法,找到这个headers和body的分界。
定义:什么是数据流?
一个输入Stream提供一个int read(char[] buff, int len)接口的方法。那么,什么是数据流?
介于read API的定义,我们可以把数据流看作潜在无限多个buff的list。其中,每个buff对象至少包含一个字节的数据(但是TCP/IP所约束的read API的规范可能不是这么说的?),也就是说,len(buff)>=1。
C++中有rope的概念,用于描述list<char[]>这一概念。它可以认为是标准string对象的内存存储优化的实现。
原始方法
把list<char[]>拼接为一个string对象,然后调用find/index/search方法。
缺点:每次拼接操作会导致内存分配和memcpy,导致性能开销太大,并有可能引入动态内存分配触发的大延迟,影响实际系统中的可用性。
学术上的标准方法
把要查找的子串模式编译为‘AC自动机’,或者简单一点,挖掘子串内在的冗余重复,使用‘KMP’,或者可以考虑像‘BM’那样从后往前搜索。
缺点:实现复杂性太高,并且在数据流(list<char[]>)这种特殊的数据结构上还要做修改适配。
实用的简单算法
考虑下面的几点:
- 对数据流而言,存在‘滑动窗口’的概念,也就是说,子串“\r\n\r\n”只有4个字节,理论上,在上次搜索操作没有找到的情况下,理论上,总是查找最近没有搜索的‘滑动窗口’长度的输入即可。
- 问题是,“\r\n\r\n”可能在2个(或更多)buff边界处分割
- 那也就是说,我们需要把原始的数据流list<char[]>对象拆分为2+1类:已经被扫描但没有找到的;待扫描的(这一概念相当于一个滑动窗口);以及待处理的。
- 待扫描的最多只需要保存4个buff对象(!),我们可以把这部分buff对象简单地拼接为一个string对象,如果找到,直接返回
- 如果没有找到,则丢弃第1个buff对象(append到‘已经被扫描但没有找到的’list的最后),算法循环继续
这一算法本质上还是原始的string.find,关键是它为‘数据流’这一限制作了必要的修改,以避免大内存的动态分配开销。
0 0
- Python:数据流中查找特定子串的简单算法
- 删除字符串中特定的子串
- Python 在列表list中查找特定的值
- viewWithTag简单用法 寻找视图中特定的子视图
- 查找所有特定子串并删除
- python 字符串中查找子串
- Linux在指定文件夹及其子文件夹中查找包含特定文本的文件
- 如何在一个布局中,查找特定类型的子控件
- 查找子串的索引位置算法
- 子串查找的算法-----BM
- Python 查找Twitter中特定话题中最流行的10个转发Tweet
- Python 查找Twitter中特定话题中最流行(转载最多)的10个Tweet
- 在字符串中查找子字符串的算法
- 在字符串中查找子字符串的算法
- 在字符串中查找子字符串的算法
- 查找子字符串的算法
- vue 中数据流 状态的简单介绍
- Python 正则表达式查找字符串中特定字符
- 不透明度16进制值
- 给Xcode增加复制行、删除行快捷键的方法
- ES 分页查询
- Linux大数据开发基础:第九节:Shell编程入门(一)
- maven tomcat plugin实现热部署
- Python:数据流中查找特定子串的简单算法
- (function(mapi){})(window.mapi = {})
- Linux中mysql以及phpmyadmin的安装与配置
- 文章标题
- 程序员应该做开源项目的 6 个原因
- 相对于父元素的绝对定位
- Caffe傻瓜系列(5):Blob,Layer and Net以及对应配置文件的编写
- 命令模式【Command Pattern 】
- ORA-00600: internal error code, arguments: [kcratr_nab_less_than_odr], [1], [315], [70505], [70506]