Bha*_*Rao 26 javascript string
我正在寻找一种方法来检查字符串是否是周期性的或使用JavaScript.
要匹配的样本字符串可以11223331122333
.然而,10101
不应该匹配.
来自python,我使用了RegEx
/(.+?)\1+$/
Run Code Online (Sandbox Code Playgroud)
但它很慢.有没有可以解决这个问题的字符串方法?
Wal*_*oss 26
下面代码的想法是考虑所有长度的子串,原始字符串可以均匀分配,并检查它们是否在原始字符串中重复.一种简单的方法是检查长度从1到长度的平方根的所有除数.如果除法产生一个整数,它们也是除数,它也是一个互补的除数.例如,对于长度为100的字符串,除数为1,2,4,5,10,互补除数为100(子字符串长度无效,因为子字符串只出现一次),50,25,20(和10) ,我们已经找到了).
function substr_repeats(str, sublen, subcount)
{
for (var c = 0; c < sublen; c++) {
var chr = str.charAt(c);
for (var s = 1; s < subcount; s++) {
if (chr != str.charAt(sublen * s + c)) {
return false;
}
}
}
return true;
}
function is_periodic(str)
{
var len = str.length;
if (len < 2) {
return false;
}
if (substr_repeats(str, 1, len)) {
return true;
}
var sqrt_len = Math.sqrt(len);
for (var n = 2; n <= sqrt_len; n++) { // n: candidate divisor
var m = len / n; // m: candidate complementary divisor
if (Math.floor(m) == m) {
if (substr_repeats(str, m, n) || n != m && substr_repeats(str, n, m)) {
return true;
}
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是比较另一个字符串的子字符串没有方法到位(例如,这将是C语言strncmp(str1, str2 + offset, length)
).
假设你的字符串长度为120,并且由长度为6的子字符串组成,重复20次.你也可以把它看作是由子力长度(子串的长度)12重复10次,子能力24次重复5次,子力量30次重复4次,或者是子能力60次重复2次(子力量由20的素数因子给出) (2*2*5)以不同的组合应用于6).现在,如果你检查你的字符串是否包含重复的60次sublength,并且检查失败,你也可以确定它不包含任何sublength,这是一个除数(即,素因子的组合)60包括6.换句话说,上述代码进行的许多检查都是多余的.例如,在长度为120的情况下,上面的代码检查(幸运的是大部分时间都很快失败)以下的长度:1,2,3,4,5,6,8,10,12,15,20,24, 30,40,60(按此顺序:1,60,2,40,3,30,4,24,5,20,6,15,8,12,10).其中,只需要以下内容:24,40,60.这些是2*2*2*3,2*2*2*5,2*2*3*5,即素数组合120( 2*2*2*3*5)每个(非重复)素数中的一个取出,或者,如果您愿意,120/5,120/3,120/2.因此,暂时忘记有效的素数因子化不是一项简单的任务,我们可以将重复子串的检查限制为子长度/ p的p子串,其中p是长度的主要因素.以下是最简单的非平凡实现:
function substr_repeats(str, sublen, subcount) { see above }
function distinct_primes(n)
{
var primes = n % 2 ? [] : [2];
while (n % 2 == 0) {
n /= 2;
}
for (var p = 3; p * p <= n; p += 2) {
if (n % p == 0) {
primes.push(p);
n /= p;
while (n % p == 0) {
n /= p;
}
}
}
if (n > 1) {
primes.push(n);
}
return primes;
}
function is_periodic(str)
{
var len = str.length;
var primes = distinct_primes(len);
for (var i = primes.length - 1; i >= 0; i--) {
var sublen = len / primes[i];
if (substr_repeats(str, sublen, len / sublen)) {
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
在我的Linux PC上试用这个代码我有一个惊喜:在Firefox上它比第一个版本快得多,但在Chromium上它更慢,只有长度为数千的字符串变得更快.最后我发现问题与distinct_primes()
创建和传递的数组有关is_periodic()
.解决方案是通过合并这两个函数来摆脱数组.代码如下,测试结果在http://jsperf.com/periodic-strings-1/5上
function substr_repeats(str, sublen, subcount) { see at top }
function is_periodic(str)
{
var len = str.length;
var n = len;
if (n % 2 == 0) {
n /= 2;
if (substr_repeats(str, n, 2)) {
return true;
}
while (n % 2 == 0) {
n /= 2;
}
}
for (var p = 3; p * p <= n; p += 2) {
if (n % p == 0) {
if (substr_repeats(str, len / p, p)) {
return true;
}
n /= p;
while (n % p == 0) {
n /= p;
}
}
}
if (n > 1) {
if (substr_repeats(str, len / n, n)) {
return true;
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
请记住,jsperf.org收集的时间是绝对的,不同机器的不同实验者将对不同的渠道组合做出贡献.如果要可靠地比较两个JavaScript引擎,则需要编辑实验的新私有版本.
Jam*_*rpe 12
一种选择是继续使用正则表达式,但通过删除以下内容使其变得贪婪?
:
/^(.+)\1+$/
Run Code Online (Sandbox Code Playgroud)
根据确切的输入字符串,它可以减少所需的回溯量并加快匹配.
小智 5
如果字符串是周期性的:
因此,我们可以制作一个超级贪心算法,该算法采用最后一个元素并检查出现长度的一半.当我们找到一个时,我们检查子串的长度是否除以主长度,然后我们将对该字符串进行测试.
function periodic(str){
for(var i=0; i<=str.length/2; i++){
if(str[i] === str[str.length-1] && str.length%(i+1) === 0){
if (str.substr(0,i+1).repeat(str.length/(i+1)) === str){
return true;
}
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1597 次 |
最近记录: |