繁体   English   中英

Java String 类中 replaceAll() 函数的内部工作

[英]Internal working of replaceAll() function in String class, Java

我访问了多个网站只是为了了解 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 循环)。

提前致谢。

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

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

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

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

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

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

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

有关汤普森 / NFA 的更多信息。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM