问题描述
我已经访问了多个网站,只是想了解String类中使用的任何regex函数的内部工作原理,例如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循环)。 / p>
谢谢。
解决方法
正则表达式太复杂了,无法进行如此简单的分析。
有一个叫做Thompson / NFA regexp解析器的东西。这种正则表达式解析器具有O(n + m)性能,其中n是正则表达式的长度,而m是输入字符串的长度。但是,TNFA无法处理反向引用,各种前瞻/回溯以及其他问题。一旦您在正则表达式中开始使用这些“ TNFA取消资格”功能,实际上不可能会从正则表达式引擎中挤出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的regex引擎中的regex花费的时间长得多。
有关Thompson / NFA的更多信息。
re2j is a java implementation of Thompson/NFA。如果要在Java中保证线性性能(O(n+m)
)正则表达式,请使用此选项。正如数学上所指示的那样,re2j不支持反向引用和其他一些功能(请参见列表中的站点),因此它无法运行您的(.)\\1{1,}
表达式-这是因为从数学上讲,不可能在O(n)
时间。