一种支持复杂字符集的NFA高效构造方法

简介: 背景当前正则表达式NFA(非确定有穷自动机,Non-deterministic finite automaton)构造方法,通常需要先借助“堆栈(Stack)”构造“语法树(SyntaxTree)”,然后,将语法树转换为NFA。由于正则语义的嵌套层级未知,导致堆栈的大小不可控,容易导致内存溢出错误,并且,构造语法树也需要一定的消耗CPU。同时,传统的NFA在复杂字符集的情况下,采用邻接矩阵(全量数

背景

当前正则表达式NFA(非确定有穷自动机,Non-deterministic finite automaton)构造方法,通常需要先借助“堆栈(Stack)”构造“语法树(SyntaxTree)”,然后,将语法树转换为NFA。由于正则语义的嵌套层级未知,导致堆栈的大小不可控,容易导致内存溢出错误,并且,构造语法树也需要一定的消耗CPU。同时,传统的NFA在复杂字符集的情况下,采用邻接矩阵(全量数组)或邻接表的方式存储状态跳转,存在空间存储较大或者匹配性能较差的问题。

本文,消除构造“语法树(SyntaxTree)”环节,采用有序邻接区间表的存储方式,实现了一种无需申请额外的“堆栈(Stack)”空间且存储空间压缩率较高的正则表达式NFA高效构造方法。

怎么实现的?

本文提出一种支持复杂字符集的NFA高效构造方法,无需开辟额外的“堆栈(Stack)”空间,进而避免出现内存溢出错误,无需创建“语法树(SyntaxTree)”,进而加快了构造速度,采用有序邻接区间表,较好的实现了复杂字符集功能。系统模块设计分为三部分:正则预处理、NFA构造。

   A)正则预处理,用于判定是否需要在头部增加“前缀.*”。

正则匹配模式包含两种:搜索和匹配。“搜索”表示字符串是否包含符合正则表达式的子串,“匹配”表示整个字符串是否符合正则表达式。

如果正则匹配为“搜索”模式,并且正则第一个字符不是“^”(字符^用于限定开头),则需要为此正则表达式增加“前缀.*”。例如:搜索模式的正则表达式“abc”,在头部增加“前缀.*”得到的正则表达式为“.*abc”。

   B)NFA构造。遍历正则表达式,同步构造NFA,无需创建“语法树(SyntaxTree)”。

1.创建“当前自动机nowNfa”。

2.遍历正则表达式,根据“当前字符currentCharacter”所属的字符类型(字符转换、量词、或、小括号),分别执行对应操作。

(1)字符转换

如果“当前字符currentCharacter”为“转义字符”,则解析“转义字符”、“16进制”、“8进制”得到“结果字符集resultCharSet”。

如果“当前字符currentCharacter”为“非元字符”,则解析为只包含“非元字符”的“结果字符集resultCharSet”。

如果“当前字符currentCharacter”为“任意字符.”,则解析为包含“所有字符”的“结果字符集resultCharSet”。

如果“当前字符currentCharacter”为“区间值[]”,则解析为包含“所有区间值”的“结果字符集resultCharSet”。

默认情况,解析为只包含“一个字符”的“结果字符集resultCharSet”。

如果“下一个字符nextChar”为“量词”,则将当前结果转化为“下一个自动机nextNfa”。否则,为“当前自动机nowNfa”根据“结果字符集resultCharSet”添加跳转操作。

如果“结果字符集resultCharSet”包含了汉语,例如:“.*中国.*”、“ [\u4e00-\u9fa5]”、[^abc],此时跳转表仅采用包含256个元素的数组不能表达上述语义,需要在后面采用“有序区间邻接表”表示超出常见字符集的复杂字符集部分。小于256的常见字符集通过数组索引能够直接定位,超过255的部分需要采用二分查找模式判定匹配结果。

(2)量词

如果“当前字符currentCharacter”为“*”,则解析值为“{0,+∞}”的“量词区间countInterval”。

如果“当前字符currentCharacter”为“?”,则解析值为“{0,1}”的“量词区间countInterval”。

如果“当前字符currentCharacter”为“+”,则解析值为“{1,+∞}”的“量词区间countInterval”。

如果“当前字符currentCharacter”为“{”,则解析值为“{m,n}”的“量词区间countInterval”。

量词复制操作repeat会造成状态膨胀,比如形如{10000}的量词会repeat10000次,由此也会创建10000个NFA状态,这种情形极易造成内存超限。为此本文在量词操作repeat前做了次数阈值限定,如果repeat次数超过阈值(比如:10),则转换为量词节点自转换操作nodeSelfConvert,此操作采用“标记位Tag”和“计数器Counter”的方式表示此量词。在匹配过程中遇到此类型的“标记位Tag”,需要比较当前“计数器Counter”是否符合量词限定,如果符合则继续执行匹配操作,同时将当前“计数器Counter”加1。

首先,判断根据量词是否超过阈值,然后,确定针对“下一个自动机nextNfa”执行量词复制操作repeat还是量词节点自转换操作nodeSelfConvert,最后,针对“当前自动机nowNfa”和“下一个自动机nextNfa”执行连接操作connact。

(3)或

如果“当前字符currentCharacter”为“|”,则针对“后续的正则表达式子串”构造“单独的自动机newNfa”。

针对“当前自动机nowNfa”和“单独的自动机newNfa”执行或操作or。

(4)小括号

如果“当前字符currentCharacter”为“(”,则针对 “处于小括号内正则表达式子串”构造“单独的自动机newNfa”。

针对“当前自动机nowNfa”和“单独的自动机newNfa”执行连接操作connact。

    支持复杂字符集的NFA高效构造算法执行参照:

                    

                                                                                                                                                                     

有哪些实际价值?

1)构造时间短:遍历正则表达式的同时,直接构造了NFA,无需中间结果“语法树(SyntaxTree)”,效率较高,程序具体较短的执行时间。                                             

2)内存可控:程序执行过程中无需额外申请与“正则串长度成正比”的“堆栈(Stack)”内存空间,避免内存溢出风险,保障程序正常运行。

3)匹配效率高:高频使用的前256个字符采用数组方式存储可以直接定位,其他复杂字符集采用有序邻接区间表采用二分查找定位,上述两种类型的匹配效率均较高。

相关文章
|
18天前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
XML Java 数据格式
Java 实现汉字按照26个英文首字母分组排序(实际业务方法改造)
Java 实现汉字按照26个英文首字母分组排序(实际业务方法改造)
424 0
Java 实现汉字按照26个英文首字母分组排序(实际业务方法改造)
|
18天前
火山中文编程 -- 类、方法、参数
火山中文编程 -- 类、方法、参数
150 0
|
11月前
|
数据安全/隐私保护
学生系统优化——字符限定
学生系统优化——字符限定
|
11月前
|
SQL IDE Java
如何高效编码? 使用有意义的命名
编码中随处可见命名。我们给变量、函数、参数、类和包命名;我们jar文件命名。我们命名,命名,不断命名,既然有怎么多命名要做,不妨就做好它。
|
前端开发 程序员 C#
【C#】通过扩展对象的方式,对字符串等数据类型进行数据进一步处理
在本篇文章中,我们讲一起了解下对象扩展的使用 在实际项目开发中,对象扩展使用的场景还是挺多的,比如:需要对时间值进行再处理,或者字符串中的斜杠(/)转为反斜杠(\)
96 0
|
前端开发 Java
店铺业务场景分析、BigDecimal是Java提供的一个不变的、任意精度的有符号十进制数对象。它提供了四个构造器,有两个是用BigInteger构造、接口怎么使用的、重载与重写的区别?分别是什么?
店铺业务场景分析 一、协同店铺、竞争店铺极海数据返回给前端数据结构不一样 导入的数据结构 很有可能和自定义采集得到的数据结构不一样
135 1
店铺业务场景分析、BigDecimal是Java提供的一个不变的、任意精度的有符号十进制数对象。它提供了四个构造器,有两个是用BigInteger构造、接口怎么使用的、重载与重写的区别?分别是什么?
|
Java 调度
序列化和编码的不同点
序列化和编码的不同点
164 0
序列化和编码的不同点
|
存储 关系型数据库 MySQL
何为字符集
何为字符集
114 0
何为字符集
|
算法 Java 大数据
提升Java字符串编码解码性能的技巧
常见的字符串编码有LATIN1、UTF-8、UTF-16、GB18030,他们各有各的特点,且之间的转换比较复杂。本文将为大家介绍提升Java字符串编码解码性能的技巧。
提升Java字符串编码解码性能的技巧

热门文章

最新文章