【问题标题】:Internal working of replaceAll() function in String class, JavaJava String 类中 replaceAll() 函数的内部工作
【发布时间】:2020-12-25 01:24:32
【问题描述】:

我访问了多个网站,只是为了了解 String 类中使用的任何正则表达式函数的内部工作原理,例如 split() 和 replaceAll()。

问题陈述在这里:https://www.hackerearth.com/practice/basic-programming/implementation/basics-of-implementation/practice-problems/algorithm/one-string-no-trouble-37037871/

我的代码:

String s = "abaaccasdraaaadsfd";
s = s.replaceAll("(.)\\1{1,}", "$17$1");
String[] s2 = s.split("7");
int len = 0;
for(String a : s2) {
    if(a.length() > len) {
        len = a.length();
    }
}
System.out.println(len);

在线通用代码:

String s = "abaaccasdraaaadsfd";
int count=0;
int max=0;
for(int i=1;i<str.length();i++){
    char ch =str.charAt(i-1);
    char ch1=str.charAt(i);
    if(ch!=ch1){
        count++;
        if(max<count){
            max=count;
        }
    }else{
        count=0;
    }
}
System.out.println(max+1);

我想了解正则表达式是否在 O(n) 内部运行,其中 n 是字符串的长度,那么我的代码(使用正则表达式)在时间复杂度方面类似于一般在线代码(使用 for 循环)。

提前致谢。

【问题讨论】:

    标签: java regex string time-complexity replaceall


    【解决方案1】:

    正则表达式对于这种简单的分析来说太复杂了。

    有一种叫做 Thompson/NFA 正则表达式解析器的东西。这样的正则表达式解析器具有 O(n+m) 的性能,其中 n 是正则表达式的长度,m 是输入字符串的长度。然而,TNFA 无法处理反向引用、各种前瞻/后视以及其他问题。一旦您开始在 regexp 中使用这些“TNFA 取消资格”功能,实际上不可能从您的 regexp 引擎中挤出 o(n+m) 性能。对此的证明是相当微不足道的。这个正则表达式:

    /^1?$|^(11+?)\1+$/

    将匹配长度为质数且仅由“1”符号组成的输入字符串。它会失败其他事情。

    这项工作(检查是否素数)不能在 O(n) 中完成。因此,任何能够运行上述正则表达式的正则表达式解析器都不能是O(n+m),QED。

    现在,一个相关的问题是:如果输入正则表达式仅使用基本特征,这样正则表达式可以由 Thompson/NFA 样式状态机处理,java 是否使用它,否则回退到简单的回溯实现?

    答案似乎与您的问题无关,因为您在这里使用回溯。但是,如果有记忆,java 不会附带 TNFA 实现,并且将始终使用回溯器。然而,这并没有写入规范,因此一些未来的版本可以根据输入正则表达式中使用的特性智能地切换实现。当前(从 JDK14 开始)实现完全支持 java.util.regexp.Pattern 类的 javadoc 中解释的整个功能集(其中包括 TNFA 引擎无法执行的功能,例如回溯),这确实意味着某些与 Thompson/NFA 引擎相比,Java 的正则表达式引擎中的正则表达式花费的时间要长许多数量级。

    关于Thompson / NFA的更多信息。

    re2j is a java implementation of Thompson/NFA。如果您希望在 java 中保证线性性能 (O(n+m)) 正则表达式,请使用此选项。按照数学规定,re2j 不支持反向引用和其他一些东西(请参阅该站点的列表),因此它无法运行您的 (.)\\1{1,} 表达式 - 这是因为从数学上讲,在 @987654326 中不可能这样做@时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-27
      • 2011-07-08
      • 2018-07-10
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多