澳门新浦京8455com有限公司欢迎您!

Ruby 2.7.0 稳定版发布:引入模式匹配、紧凑 GC,改进 REPL

时间:2020-02-13 08:15

Ruby 2.7.0 稳定版在圣诞节当天发布了,此版本引入了许多新特性和性能改进,最值得注意的包括:

JRuby 1.1.6发布了,主要更新包括:改进Ruby 1.9支持,支持Ruby 1.9语法分析支持。新的JRuby包括几乎所有的Ruby 1.9库,完全的Ruby 1.9库支持将在2009年第一季发布。新的release notes着重于介绍了 org.jruby.javasupport.JavaEmbedUtils类,这个类对于开发者嵌入JRuby进入正常的Java代码很有帮助。JavaEmbedUtils 类允许初始化JRuby实例,调用函数,转换Ruby类型为Java类型等等。点击这里下载: 1.1.6 release notes:+1.1.6+Released详情查看:JRuby 1.1.6 Released, Improves Ruby 1.9 Support

澳门新浦京8455com 1

一、简介

在说改进的模式匹配(KMP)算法之前我们先说朴素的模式匹配:
其实很简单,就是两个字符串逐位比较。在模式匹配中:我们假定字符串P在字符串T中查找是否有匹配的。此时,称P为模式(Pattern)字符串,称T为目标(Target)字符串。
OK,我一般比较喜欢以实例说明问题。
T: a b d a b d a b c
P: a b d a b c
朴素的模式匹配算法
朴素的模式匹配算法就是用P和T依次比较,即为:
第一趟比较:

 T:        a  b  d  a  b  d  a  b  c 
 P:        a  b  d  a  b  c

           发现第6个元素(下标为5)d和c不相等,第一趟结束,此时比较了6次(6个元素)。

第二趟比较:

   T:        a  b  d  a  b  d  a  b  c 
   P:           a  b  d  a  b  c

               第一个元素就不相等,第二趟结束,此时比较了1次(1个元素)。

第三趟比较:

T:        a  b  d  a  b  d  a  b  c 
   P:              a  b  d  a  b  c

     第一个元素就不相等,第三趟结束,此时比较了1次(1个元素)。

第四趟比较:

T:        a  b  d  a  b  d  a  b  c 
   P:                 a  b  d  a  b  c

     第一个元素相等,第二个元素也相等,第三、四、五、六都相等,匹配成功,第四趟结束,此时比较了6次(6个元素)。

匹配成功,共比较14次。但是这个是我们理想状态下的匹配方案,实际中字符串的长度远远不止这些。这种算法是一种带回逆的算法,成为朴素的模式匹配算法。

改进的模式匹配(KMP)算法
KMP算法就是消除了朴素匹配的回逆,利用一个失效函数(failure function)替代直接的回逆。思路如下:
第一趟比较:
T: a b d a b d a b c
P: a b d a b c
发现第6个元素(下标为5)d和c不相等。此时,进入一个P串的处理:
此时取出P串, a b d a b c 因为是c不和d不匹配,去掉此项,获得
a b d a b
此时判断 a b d a 是否与 b d a b 相等? 不等,进入下一轮判断
此时判断 a b d 是否与 d a b 相等? 不等,进入下一轮判断
此时判断 a b 是否与 a b 相等? 相等,结束第一趟总体判断。
(先不要急,接下来我就会说为什么这样匹配和这样匹配的用途!)
然后直接拿d和字符串中不匹配的那一项进行比较。
以上就是KMP的流程,为什么要这样做?在一些串中,目标串会远远长于模式串,如果每次都江模式串和目标串一一比较。此时时间复杂度当增加,而且在模式串中会出现很多的无效匹配,相当于无用功。但是假如先在模式串中进行比较,因为模式串会远远短于目标串,所以会相当减少时间复杂度。

  • 模式匹配(Pattern Matching)
  • REPL 改进
  • 紧凑 GC(Compaction GC)
  • 位置参数和关键字参数的分离

4MLinux是一个轻量级的Linux发行版,专注于维护(如系统拯救live CD)、多媒体(用于播放视频dvd和其他多媒体文件)和迷你服务器(使用inetd守护进程)。该项目的最新版本是4MLinux 24.0,可在桌面和服务器版本中使用。

二、next数组的理解

澳门新浦京8455com,对于KMP算法来说,重点就是 next数组 (也有叫覆盖函数,部分匹配表,lps数组等)。

总之就是 对模式串做预处理,而且该预处理只和 模式串(pattern)本身有关!

假设有模式串 pattern = “abababca”; 则有匹配表:

char:  | a | b | a | b | a | b | c | a |
index: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
value: | 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 |

下面介绍《部分匹配表》是如何产生的。

首先,要了解两个概念:”前缀”和”后缀”。 “前缀”指除了最后一个字符以外,一个字符串的全部头部组合;”后缀”指除了第一个字符以外,一个字符串的全部尾部组合。

字符串:   "bread"

前缀: b , br, bre, brea

后缀:  read, ead, ad ,  d

关于 next数组 (也有叫覆盖函数,部分匹配表,lps数组) 的通俗解释:”部分匹配值”就是”前缀”和”后缀”的最长的共有元素的长度。以”ABCDABD”为例,

    "A"的前缀和后缀都为空集,共有元素的长度为0;
    "AB"的前缀为[A],后缀为[B],共有元素的长度为0;
 "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
 "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
 "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;
 "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;
 "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

下面举个例子

pattern “AABAACAABAA”, next[] is [0, 1, 0, 1, 2, 0, 1, 2, 3, 4, 5]
pattern “ABCDE”, next[] is [0, 0, 0, 0, 0]
pattern “AAAAA”, next[] is [0, 1, 2, 3, 4]
pattern “AAABAAA”, next[] is [0, 1, 2, 0, 1, 2, 3]
pattern “AAACAAAAAC”, next[] is [0, 1, 2, 0, 1, 2, 3, 3, 3, 4]

代码如下:

/*
* function          生成部分匹配表,next数组
* param     subStr  模式串,子串
* param     next    next数组,部分匹配信息表
* param     len     next数组的长度,一般就是模式串的长度
* return            无
*/
void GetNext(const char* subStr, int* next, int len)
{
    memset(next, 0, len);
    int prefix = -1; //前缀
    int suffix = 0; //后缀
    next[0] = -1;    //第一个元素只是用来控制prefix和suffix后移的
    while (suffix < len - 1)//当比较到最后一个字符的时候退出循环
    {
        /*
        当prefix == -1的时候表示要从prefix=0,suffix=1开始比较
        若prefix != -1,表示前缀和后缀已经有重合的了,接着往后移比较
        例如:subStr="ABABABB"
            1.prefix=-1,往后移,prefix=0,suffix=1,next[1] = 0,表示字符串‘A’前缀后缀无重合

            2.prefix=0,比较subStr[0]和subStr[1]('A'和'B'),不相等,把prefix重新置为next[prefix](next[0]==-1)

            3.prefix=-1,往后移,prefix=0,suffix=2,next[2] = 0,表示字符串‘AB’前缀后缀无重合

            4.prefix=0,比较subStr[0]和subStr[2]('A'和'A'),相等,继续往后移,prefix=1,suffix=3,next[3]=1
              表示字符串"ABA"有一个字符前缀后缀相等('A'和'A')

            5.prefix=1,比较subStr[1]和subStr[3]('B'和'B'),相等,继续往后移,prefix=2,suffix=4,next[4]=2
              表示字符串"ABAB"有两个字符前缀后缀相等('AB'和'AB')

            6.prefix=2,比较subStr[2]和subStr[4]('A'和'A'),相等,继续往后移,prefix=3,suffix=5,next[5]=3
              表示字符串"ABABA"有三个字符前缀后缀相等('ABA'和'ABA')

            7.prefix=3,比较subStr[3]和subStr[5]('B'和'B'),相等,继续往后移,prefix=4,suffix=6,next[6]=4
              表示字符串"ABABAB"有四个字符前缀后缀相等('ABAB'和'ABAB')

            8.当suffix=6最后一个的时候,就不需要比较了,因为KMP算法中最后一个并无指导匹配的作用,因为一旦前6个匹配成功,最后一个
              就算不成功,用到的也是前一个的部分匹配信息,若是成功那就直接返回了,所以求next数组的时候,最后一个的信息省略  

        */
        if (prefix == -1 || subStr[prefix] == subStr[suffix])
        {
            ++prefix, ++suffix;           
            next[suffix] = prefix;
            printf("%d ", next[suffix]);  //测试用,可删除
        }
        else
            prefix = next[prefix];
    }
    printf("n");     //测试用,可删除
}

模式匹配(实验性功能)

模式匹配是函数式编程语言中广泛使用的特性,如果匹配某一个模式,它可以遍历给定的对象并分配其值,目前尚处于实验阶段 [Feature #14912]:

require "json"

json = <<END
{
  "name": "Alice",
  "age": 30,
  "children": [{ "name": "Bob", "age": 2 }]
}
END

case JSON.parse(json, symbolize_names: true)
in {name: "Alice", children: [{name: "Bob", age: age}]}
  p age #=> 2
end

有关该功能的具体细节请查看 Pattern matching - New feature in Ruby 2.7。

4MLinux 24.0系列的状态已经更改为稳定。编辑你的文档LibreOffice 6.0.0.1和GNOME办公室(AbiWord 3.0.2,GIMP 2.8.22,Gnumeric 1.12.38),分享你的文件使用DropBox 43.4.49,与Firefox 58.0.2和铬64.0.3282.119上网,与你的朋友保持联系通过雷鸟52.6.0和Skype的网络,享受你的音乐收藏与大胆的3.9,看你最喜欢的视频VLC 3.0.0和媒体播放器SVN-r37946,玩游戏由台面17.1.4 3.1和葡萄酒。您还可以设置4MLinux LAMP服务器(Linux 4.14.18、Apache 2.4.29、MariaDB 10.2.12、PHP 5.6.33和PHP 7.2.2)。Perl 5.26.0和Python 2.7.13也是可用的。进一步的信息可以在项目的发布公告中找到。

三、KMP模式匹配算法

int Index_KMP(char *s,char *p,int pos,int next[])
/*利用模式串p的next函数,求p在主串中从第pos个字符开始的位置*/
/*若匹配成功,则返回模式串在主串中的位置(下标),否则返回-1。设模式串第一个字符的下标为0*/
{
  int i,j,slen,plen;
  i = pos-1;
  j=-1;
  slen = strlen(s);plen = strlen(p);
  while(i<slen&&j<plen){
    if(j==-1||s[i]==p[j]){++i;++j;}
        else j = next[j];
  }
  if(j>=plen)return i-plen;
  else return -1;

REPL 改进

绑定的交互式环境 irb 现在支持多行编辑,由 reline 提供支持,reline 是一种与 readline 兼容的纯 Ruby 实现。它还提供了 rdoc 集成。在 irb 中,可以显示给定类、模块或方法的引用。此外,binding.irb 中显示的源代码行和核心类对象的检查结果现在以颜色区分显示。

澳门新浦京8455com 2

4MLinux 24.0系列的状态已更改为稳定。 使用LibreOffice 6.0.0.1和GNOME Office(AbiWord 3.0.2,GIMP 2.8.22,Gnumeric 1.12.38)编辑文档,使用DropBox 43.4.49共享文件,使用Firefox 58.0.2和Chromium 64.0.3282.119浏览互联网 ,通过Thunderbird 52.6.0和Skype for Web与您的朋友保持联系,使用Audacious 3.9享受您的音乐收藏,使用VLC 3.0.0和MPlayer SVN-r37946观看您最喜爱的视频,玩游戏由Mesa 17.1.4和Wine 3.1提供支持。