How do I check if a string is entirely made of the same substring? Unicorn Meta Zoo #1: Why...
Check if a string is entirely made of the same substring
Book with legacy programming code on a space ship that the main character hacks to escape
How to get even lighting when using flash for group photos near wall?
Would reducing the reference voltage of an ADC have any effect on accuracy?
A strange hotel
Multiple options vs single option UI
Multiple fireplaces in an apartment building?
Seek and ye shall find
My bank got bought out, am I now going to have to start filing tax returns in a different state?
Does Feeblemind produce an ongoing magical effect that can be dispelled?
Additive group of local rings
Could moose/elk survive in the Amazon forest?
Why did C use the -> operator instead of reusing the . operator?
c++ diamond problem - How to call base method only once
Is Bran literally the world's memory?
"Rubric" as meaning "signature" or "personal mark" -- is this accepted usage?
What is ls Largest Number Formed by only moving two sticks in 508?
What is the best way to deal with NPC-NPC combat?
As an international instructor, should I openly talk about my accent?
All ASCII characters with a given bit count
Did the Roman Empire have penal colonies?
How would I use different systems of magic when they are capable of the same effects?
What's the difference between using dependency injection with a container and using a service locator?
Are all CP/M-80 implementations binary compatible?
How do I check if a string is entirely made of the same substring?
Unicorn Meta Zoo #1: Why another podcast?
Announcing the arrival of Valued Associate #679: Cesar Manara
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!How to check empty/undefined/null string in JavaScript?How do I check if an element is hidden in jQuery?How do I check if an array includes an object in JavaScript?How to check if a string “StartsWith” another string?How do I make the first letter of a string uppercase in JavaScript?How to replace all occurrences of a string in JavaScriptHow to check whether a string contains a substring in JavaScript?How to check for “undefined” in JavaScript?Check if a variable is a string in JavaScriptHow to check if an object is an array?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have to create a function which takes a string, and it should return true
or false
based on whether the input consists of a repeated character sequence. The length of given string is always greater than 1
and the character sequence must have at least one repetition.
"aa" // true(entirely contains two strings "a")
"aaa" //true(entirely contains three string "a")
"abcabcabc" //true(entirely containas three strings "abc")
"aba" //false(At least there should be two same substrings and nothing more)
"ababa" //false("ab" exists twice but "a" is extra so false)
I have created a function, but it's:
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Checking of this is part of the real problem. I can't afford a non-efficient solution like this. First of all it's looping through half of the string.
The second problem is that its using replace()
in each loop which makes it slow. Is there a better solution regarding performance?
javascript algorithm
|
show 2 more comments
I have to create a function which takes a string, and it should return true
or false
based on whether the input consists of a repeated character sequence. The length of given string is always greater than 1
and the character sequence must have at least one repetition.
"aa" // true(entirely contains two strings "a")
"aaa" //true(entirely contains three string "a")
"abcabcabc" //true(entirely containas three strings "abc")
"aba" //false(At least there should be two same substrings and nothing more)
"ababa" //false("ab" exists twice but "a" is extra so false)
I have created a function, but it's:
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Checking of this is part of the real problem. I can't afford a non-efficient solution like this. First of all it's looping through half of the string.
The second problem is that its using replace()
in each loop which makes it slow. Is there a better solution regarding performance?
javascript algorithm
6
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
1
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago
|
show 2 more comments
I have to create a function which takes a string, and it should return true
or false
based on whether the input consists of a repeated character sequence. The length of given string is always greater than 1
and the character sequence must have at least one repetition.
"aa" // true(entirely contains two strings "a")
"aaa" //true(entirely contains three string "a")
"abcabcabc" //true(entirely containas three strings "abc")
"aba" //false(At least there should be two same substrings and nothing more)
"ababa" //false("ab" exists twice but "a" is extra so false)
I have created a function, but it's:
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Checking of this is part of the real problem. I can't afford a non-efficient solution like this. First of all it's looping through half of the string.
The second problem is that its using replace()
in each loop which makes it slow. Is there a better solution regarding performance?
javascript algorithm
I have to create a function which takes a string, and it should return true
or false
based on whether the input consists of a repeated character sequence. The length of given string is always greater than 1
and the character sequence must have at least one repetition.
"aa" // true(entirely contains two strings "a")
"aaa" //true(entirely contains three string "a")
"abcabcabc" //true(entirely containas three strings "abc")
"aba" //false(At least there should be two same substrings and nothing more)
"ababa" //false("ab" exists twice but "a" is extra so false)
I have created a function, but it's:
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Checking of this is part of the real problem. I can't afford a non-efficient solution like this. First of all it's looping through half of the string.
The second problem is that its using replace()
in each loop which makes it slow. Is there a better solution regarding performance?
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
function check(str){
if(!(str.length && str.length - 1)) return false;
let temp = '';
for(let i = 0;i<=str.length/2;i++){
temp += str[i]
//console.log(str.replace(new RegExp(temp,"g"),''))
if(!str.replace(new RegExp(temp,"g"),'')) return true;
}
return false;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
javascript algorithm
javascript algorithm
edited 14 hours ago
Peter Mortensen
14k1987114
14k1987114
asked 19 hours ago
Maheer AliMaheer Ali
12.7k1230
12.7k1230
6
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
1
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago
|
show 2 more comments
6
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
1
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago
6
6
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
1
1
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago
|
show 2 more comments
8 Answers
8
active
oldest
votes
You can do it by a capturing group and backreference. Just check it's the repetition of the first captured value.
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
In the above RegExp:
^
and$
stands for start and end anchors to predict the position.
(.+)
captures any pattern and captures the value(exceptn
).
1
is backreference of first captured value and1+
would check for repetition of captured value.
Regex explanation here
For RegExp debugging use: https://regex101.com/r/pqlAuP/1/debugger
Performance : https://jsperf.com/regex-and-loop/1
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?
– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
You can use[sS]
instead of.
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive(.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple.
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.
– HappyDog
16 hours ago
|
show 11 more comments
Perhaps the fastest algorithmic approach is building a Z-function in linear time:
The Z-function for this string is an array of length n where the i-th
element is equal to the greatest number of characters starting from
the position i that coincide with the first characters of s.
In other words, z[i] is the length of the longest common prefix
between s and the suffix of s starting at i.
C++ implementation for reference:
vector<int> z_function(string s) {
int n = (int) s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
JavaScript implementation:
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
Then you need to check indexes i
that divide n. If you find such i
that i+z[i]=n
then the string s
can be compressed to the length i
and you can return true
.
For example, for
string s= 'abacabacabac' with length n=12`
z-array is
(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)
and we can find that for
i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`
so s
might be represented as substring of length 4 repeated three times.
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
Alternate approach by avoiding an additional iterationconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
add a comment |
Assume the string S has length N and is made of duplicates of the substring s, then the length of s divides N. For example, if S has length 15, then the substring has length 1, 3, or 5.
Let S be made of (p*q) copies of s. Then S is also made of p copies of (s, repeated q times). We have therefore two cases: If N is prime or 1, then S can only be made of copies of the substring of length 1. If N is composite, then we only need to check substrings s of length N / p for primes p dividing the length of S.
So determine N = the length of S, then find all its prime factors in time O (sqrt (N)). If there is only one factor N, check if S is the same string repeated N times, otherwise for each prime factor p, check if S consists of p repeations of the first N / p characters.
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
add a comment |
I think a recursive function might be very fast as well. The first observation is that the maximum repeated pattern length is half as long as the total string. And we could just test all possible repeated pattern lengths: 1, 2, 3, ..., str.length/2
The recursive function isRepeating(p,str) tests if this pattern is repeated in str.
If str is longer than the pattern, the recursion requires the first part (same length as p) to be a repetition as well as the remainder of str. So str is effectively broken up into pieces of length p.length.
If the tested pattern and str are of equal size, recursion ends here, successfully.
If the length is different (happens for "aba" and pattern "ab") or if the pieces are different, then false is returned, propagating up the recursion.
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Performance: https://jsperf.com/reegx-and-loop/13
1
Would it be faster to checkif( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?
– Chronocidal
10 hours ago
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
|
show 3 more comments
My approach is similar to gnasher729, in that it uses the potential length of the substring as the main focus, but it is less math-y and process intensive:
L: Length of original string
S: Potential lengths of valid sub-strings
Loop S from (integer part of) L/2 to 1. If L/S is an integer check your original string against the fist S characters of the original string repeated L/S times.
The reason for looping from L/2 backwards and not from 1 onwards is to get the largest possible substring. If you want the smallest possible substring loop from 1 to L/2. Example: "abababab" has both "ab" and "abab" as possible substrings. Which of the two would be faster if you only care about a true/false result depends on the type of strings/substrings this will be applied to.
add a comment |
I read the answer of gnasher729 and implemented it.
The idea is that if there are any repetitions, then there must be (also) a prime number of repetitions. If you want performance, this is what you want.
function* primeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
function check (str) {
var n = str.length
primeloop:
for (p of primeFactors(n)) {
var l = n/p
var s = str.substring(0, l)
for (var j=1; j<p; j++) {
if (s != str.substring(l*j, l*(j+1))) continue primeloop
}
return true
}
return false
}
I've updated the jsPerf page that contains the algorithms used on this page.
add a comment |
I'm not familiar with JavaScript, so I don't know how fast this is going to be, but here is a linear time solution (assuming reasonable builtin implementation) using only builtins. I'll describe the algorithm in pseudocode.
function check(str) {
t = str + str;
find all overlapping occurrences of str in t;
for each occurrence at position i
if (i > 0 && i < str.length && str.length % i == 0)
return true; // str is a repetition of its first i characters
return false;
}
The idea is similar to MBo's answer. For each i
that divides the length, str
is a repetition of its first i
characters if and only if it remains the same after shifting for i
characters.
It comes to my mind that such a builtin may be unavailable or inefficient. In this case, it is always possible to implement the KMP algorithm manually, which takes about the same amount of code as the algorithm in MBo's answer.
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its lengthi
,s[0:n-i] == s[i:n]
, or equivalently,s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?
– infmagic2047
57 mins ago
add a comment |
One of the simple ideas is to replace the string with the substring of "" and if any text exist then it is false, else it is true.
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
4
What aboutabcabcabc
orunicornunicorn
?
– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55823298%2fhow-do-i-check-if-a-string-is-entirely-made-of-the-same-substring%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can do it by a capturing group and backreference. Just check it's the repetition of the first captured value.
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
In the above RegExp:
^
and$
stands for start and end anchors to predict the position.
(.+)
captures any pattern and captures the value(exceptn
).
1
is backreference of first captured value and1+
would check for repetition of captured value.
Regex explanation here
For RegExp debugging use: https://regex101.com/r/pqlAuP/1/debugger
Performance : https://jsperf.com/regex-and-loop/1
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?
– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
You can use[sS]
instead of.
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive(.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple.
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.
– HappyDog
16 hours ago
|
show 11 more comments
You can do it by a capturing group and backreference. Just check it's the repetition of the first captured value.
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
In the above RegExp:
^
and$
stands for start and end anchors to predict the position.
(.+)
captures any pattern and captures the value(exceptn
).
1
is backreference of first captured value and1+
would check for repetition of captured value.
Regex explanation here
For RegExp debugging use: https://regex101.com/r/pqlAuP/1/debugger
Performance : https://jsperf.com/regex-and-loop/1
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?
– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
You can use[sS]
instead of.
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive(.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple.
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.
– HappyDog
16 hours ago
|
show 11 more comments
You can do it by a capturing group and backreference. Just check it's the repetition of the first captured value.
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
In the above RegExp:
^
and$
stands for start and end anchors to predict the position.
(.+)
captures any pattern and captures the value(exceptn
).
1
is backreference of first captured value and1+
would check for repetition of captured value.
Regex explanation here
For RegExp debugging use: https://regex101.com/r/pqlAuP/1/debugger
Performance : https://jsperf.com/regex-and-loop/1
You can do it by a capturing group and backreference. Just check it's the repetition of the first captured value.
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
In the above RegExp:
^
and$
stands for start and end anchors to predict the position.
(.+)
captures any pattern and captures the value(exceptn
).
1
is backreference of first captured value and1+
would check for repetition of captured value.
Regex explanation here
For RegExp debugging use: https://regex101.com/r/pqlAuP/1/debugger
Performance : https://jsperf.com/regex-and-loop/1
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
function check(str) {
return /^(.+)1+$/.test(str)
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
edited 7 hours ago
John Kugelman
250k54407460
250k54407460
answered 19 hours ago
Pranav C BalanPranav C Balan
91.1k1492119
91.1k1492119
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?
– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
You can use[sS]
instead of.
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive(.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple.
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.
– HappyDog
16 hours ago
|
show 11 more comments
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?
– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
You can use[sS]
instead of.
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive(.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple.
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.
– HappyDog
16 hours ago
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
Can you explain to us what this line is doing return /^(.+)1+$/.test(str)
– Thanveer Shah
19 hours ago
15
15
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
Also what is the complexity of this solution? I'm not absolutely sure but it doesn't seem to be much faster than the one the OP has.
– Leron
19 hours ago
3
3
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:
If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?– Leron
18 hours ago
@PranavCBalan I'm not good at algorithms, that's why I write in the comments section. However I have several things to mention - the OP already has a working solution so he is asking for one that will give him better performance and you haven't explained how your solution will outperform his. Shorter doesn't mean faster. Also, from the link you gave:
If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).
but as you wrote you are using backreference so is it still O(n)?– Leron
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
@PranavCBalan Its showing both are fastest.
– Maheer Ali
18 hours ago
1
1
You can use
[sS]
instead of .
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive (.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple .
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.– HappyDog
16 hours ago
You can use
[sS]
instead of .
if you need to match newline characters in the same way as other characters. The dot character doesn't match on newlines; the alternative searches for all white-space and non-whitespace characters, which means that newlines are included in the match. (Note that this is faster than the more intuitive (.|[rn])
.) However, if the string definitely doesn't contain newlines, then the simple .
will be fastest. Note this will be a lot simpler if the dotall flag is implemented.– HappyDog
16 hours ago
|
show 11 more comments
Perhaps the fastest algorithmic approach is building a Z-function in linear time:
The Z-function for this string is an array of length n where the i-th
element is equal to the greatest number of characters starting from
the position i that coincide with the first characters of s.
In other words, z[i] is the length of the longest common prefix
between s and the suffix of s starting at i.
C++ implementation for reference:
vector<int> z_function(string s) {
int n = (int) s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
JavaScript implementation:
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
Then you need to check indexes i
that divide n. If you find such i
that i+z[i]=n
then the string s
can be compressed to the length i
and you can return true
.
For example, for
string s= 'abacabacabac' with length n=12`
z-array is
(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)
and we can find that for
i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`
so s
might be represented as substring of length 4 repeated three times.
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
Alternate approach by avoiding an additional iterationconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
add a comment |
Perhaps the fastest algorithmic approach is building a Z-function in linear time:
The Z-function for this string is an array of length n where the i-th
element is equal to the greatest number of characters starting from
the position i that coincide with the first characters of s.
In other words, z[i] is the length of the longest common prefix
between s and the suffix of s starting at i.
C++ implementation for reference:
vector<int> z_function(string s) {
int n = (int) s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
JavaScript implementation:
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
Then you need to check indexes i
that divide n. If you find such i
that i+z[i]=n
then the string s
can be compressed to the length i
and you can return true
.
For example, for
string s= 'abacabacabac' with length n=12`
z-array is
(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)
and we can find that for
i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`
so s
might be represented as substring of length 4 repeated three times.
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
Alternate approach by avoiding an additional iterationconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
add a comment |
Perhaps the fastest algorithmic approach is building a Z-function in linear time:
The Z-function for this string is an array of length n where the i-th
element is equal to the greatest number of characters starting from
the position i that coincide with the first characters of s.
In other words, z[i] is the length of the longest common prefix
between s and the suffix of s starting at i.
C++ implementation for reference:
vector<int> z_function(string s) {
int n = (int) s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
JavaScript implementation:
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
Then you need to check indexes i
that divide n. If you find such i
that i+z[i]=n
then the string s
can be compressed to the length i
and you can return true
.
For example, for
string s= 'abacabacabac' with length n=12`
z-array is
(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)
and we can find that for
i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`
so s
might be represented as substring of length 4 repeated three times.
Perhaps the fastest algorithmic approach is building a Z-function in linear time:
The Z-function for this string is an array of length n where the i-th
element is equal to the greatest number of characters starting from
the position i that coincide with the first characters of s.
In other words, z[i] is the length of the longest common prefix
between s and the suffix of s starting at i.
C++ implementation for reference:
vector<int> z_function(string s) {
int n = (int) s.length();
vector<int> z(n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = min (r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z;
}
JavaScript implementation:
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
Then you need to check indexes i
that divide n. If you find such i
that i+z[i]=n
then the string s
can be compressed to the length i
and you can return true
.
For example, for
string s= 'abacabacabac' with length n=12`
z-array is
(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)
and we can find that for
i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`
so s
might be represented as substring of length 4 repeated three times.
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
function z_function(s) {
var n = s.length;
var z = Array(n).fill(0);
var i, l, r;
for (i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r)
z[i] = Math.min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
++z[i];
//we can check condition and return here
// if (z[i] + i === n && n % i === 0) return true;
if (i + z[i] - 1 > r)
l = i, r = i + z[i] - 1;
}
return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));
edited 6 hours ago
answered 18 hours ago
MBoMBo
50.8k23153
50.8k23153
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
Alternate approach by avoiding an additional iterationconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
add a comment |
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
Alternate approach by avoiding an additional iterationconst check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
2
2
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
return z.some((zi, i) => (i + zi) === n && n % i === 0)
– Pranav C Balan
12 hours ago
2
2
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
Thanks for adding JavaScript stuff to Salman A and Pranav C Balan
– MBo
7 hours ago
1
1
Alternate approach by avoiding an additional iteration
const check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
Alternate approach by avoiding an additional iteration
const check = (s) => { let n = s.length; let z = Array(n).fill(0); for (let i = 1, l = 0, r = 0; i < n; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i]; // check condition here and return if (z[i] + i === n && n % i === 0) return true; if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1; } // or return false return false; }
– Pranav C Balan
7 hours ago
add a comment |
Assume the string S has length N and is made of duplicates of the substring s, then the length of s divides N. For example, if S has length 15, then the substring has length 1, 3, or 5.
Let S be made of (p*q) copies of s. Then S is also made of p copies of (s, repeated q times). We have therefore two cases: If N is prime or 1, then S can only be made of copies of the substring of length 1. If N is composite, then we only need to check substrings s of length N / p for primes p dividing the length of S.
So determine N = the length of S, then find all its prime factors in time O (sqrt (N)). If there is only one factor N, check if S is the same string repeated N times, otherwise for each prime factor p, check if S consists of p repeations of the first N / p characters.
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
add a comment |
Assume the string S has length N and is made of duplicates of the substring s, then the length of s divides N. For example, if S has length 15, then the substring has length 1, 3, or 5.
Let S be made of (p*q) copies of s. Then S is also made of p copies of (s, repeated q times). We have therefore two cases: If N is prime or 1, then S can only be made of copies of the substring of length 1. If N is composite, then we only need to check substrings s of length N / p for primes p dividing the length of S.
So determine N = the length of S, then find all its prime factors in time O (sqrt (N)). If there is only one factor N, check if S is the same string repeated N times, otherwise for each prime factor p, check if S consists of p repeations of the first N / p characters.
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
add a comment |
Assume the string S has length N and is made of duplicates of the substring s, then the length of s divides N. For example, if S has length 15, then the substring has length 1, 3, or 5.
Let S be made of (p*q) copies of s. Then S is also made of p copies of (s, repeated q times). We have therefore two cases: If N is prime or 1, then S can only be made of copies of the substring of length 1. If N is composite, then we only need to check substrings s of length N / p for primes p dividing the length of S.
So determine N = the length of S, then find all its prime factors in time O (sqrt (N)). If there is only one factor N, check if S is the same string repeated N times, otherwise for each prime factor p, check if S consists of p repeations of the first N / p characters.
Assume the string S has length N and is made of duplicates of the substring s, then the length of s divides N. For example, if S has length 15, then the substring has length 1, 3, or 5.
Let S be made of (p*q) copies of s. Then S is also made of p copies of (s, repeated q times). We have therefore two cases: If N is prime or 1, then S can only be made of copies of the substring of length 1. If N is composite, then we only need to check substrings s of length N / p for primes p dividing the length of S.
So determine N = the length of S, then find all its prime factors in time O (sqrt (N)). If there is only one factor N, check if S is the same string repeated N times, otherwise for each prime factor p, check if S consists of p repeations of the first N / p characters.
answered 10 hours ago
gnasher729gnasher729
42.2k44979
42.2k44979
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
add a comment |
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I haven't checked the other solutions, but this seems very fast. You can leave out the "If there is only one factor N, check ..., otherwise" part for simplicity, as this is not a special case. Would be nice to see a Javascript implementation that can be run in jsPerf next to the other implementations.
– user42723
8 hours ago
I've now implemented this in my answer
– user42723
4 mins ago
I've now implemented this in my answer
– user42723
4 mins ago
add a comment |
I think a recursive function might be very fast as well. The first observation is that the maximum repeated pattern length is half as long as the total string. And we could just test all possible repeated pattern lengths: 1, 2, 3, ..., str.length/2
The recursive function isRepeating(p,str) tests if this pattern is repeated in str.
If str is longer than the pattern, the recursion requires the first part (same length as p) to be a repetition as well as the remainder of str. So str is effectively broken up into pieces of length p.length.
If the tested pattern and str are of equal size, recursion ends here, successfully.
If the length is different (happens for "aba" and pattern "ab") or if the pieces are different, then false is returned, propagating up the recursion.
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Performance: https://jsperf.com/reegx-and-loop/13
1
Would it be faster to checkif( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?
– Chronocidal
10 hours ago
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
|
show 3 more comments
I think a recursive function might be very fast as well. The first observation is that the maximum repeated pattern length is half as long as the total string. And we could just test all possible repeated pattern lengths: 1, 2, 3, ..., str.length/2
The recursive function isRepeating(p,str) tests if this pattern is repeated in str.
If str is longer than the pattern, the recursion requires the first part (same length as p) to be a repetition as well as the remainder of str. So str is effectively broken up into pieces of length p.length.
If the tested pattern and str are of equal size, recursion ends here, successfully.
If the length is different (happens for "aba" and pattern "ab") or if the pieces are different, then false is returned, propagating up the recursion.
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Performance: https://jsperf.com/reegx-and-loop/13
1
Would it be faster to checkif( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?
– Chronocidal
10 hours ago
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
|
show 3 more comments
I think a recursive function might be very fast as well. The first observation is that the maximum repeated pattern length is half as long as the total string. And we could just test all possible repeated pattern lengths: 1, 2, 3, ..., str.length/2
The recursive function isRepeating(p,str) tests if this pattern is repeated in str.
If str is longer than the pattern, the recursion requires the first part (same length as p) to be a repetition as well as the remainder of str. So str is effectively broken up into pieces of length p.length.
If the tested pattern and str are of equal size, recursion ends here, successfully.
If the length is different (happens for "aba" and pattern "ab") or if the pieces are different, then false is returned, propagating up the recursion.
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Performance: https://jsperf.com/reegx-and-loop/13
I think a recursive function might be very fast as well. The first observation is that the maximum repeated pattern length is half as long as the total string. And we could just test all possible repeated pattern lengths: 1, 2, 3, ..., str.length/2
The recursive function isRepeating(p,str) tests if this pattern is repeated in str.
If str is longer than the pattern, the recursion requires the first part (same length as p) to be a repetition as well as the remainder of str. So str is effectively broken up into pieces of length p.length.
If the tested pattern and str are of equal size, recursion ends here, successfully.
If the length is different (happens for "aba" and pattern "ab") or if the pieces are different, then false is returned, propagating up the recursion.
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
Performance: https://jsperf.com/reegx-and-loop/13
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
function check(str)
{
if( str.length==1 ) return true; // trivial case
for( var i=1;i<=str.length/2;i++ ) { // biggest possible repeated pattern has length/2 characters
if( str.length%i!=0 ) continue; // pattern of size i doesn't fit
var p = str.substring(0, i);
if( isRepeating(p,str) ) return true;
}
return false;
}
function isRepeating(p, str)
{
if( str.length>p.length ) { // maybe more than 2 occurences
var left = str.substring(0,p.length);
var right = str.substring(p.length, str.length);
return left===p && isRepeating(p,right);
}
return str===p;
}
console.log(check('aa')) //true
console.log(check('aaa')) //true
console.log(check('abcabcabc')) //true
console.log(check('aba')) //false
console.log(check('ababa')) //false
edited 8 hours ago
answered 13 hours ago
Axel PodehlAxel Podehl
2,0101617
2,0101617
1
Would it be faster to checkif( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?
– Chronocidal
10 hours ago
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
|
show 3 more comments
1
Would it be faster to checkif( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?
– Chronocidal
10 hours ago
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
1
1
Would it be faster to check
if( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?– Chronocidal
10 hours ago
Would it be faster to check
if( str===p.repeat(str.length/i) ) return true;
instead of using a recursive function?– Chronocidal
10 hours ago
1
1
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
Don't put console.logs in jsperf tests, prepare the functions inside the globals section, also prepare the test strings in the globals section (sorry, cannot edit the jsperf)
– Salman A
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@Salman - good point. I just modified the jsperf from my predecessor (Pranav C), first time I used jsperf, cool tool.
– Axel Podehl
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
@SalmanA : updated : jsperf.com/regex-and-loop/1 ... thanks for the info... even I'm not familiar with it(Jsperf) ... thanks for the information
– Pranav C Balan
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
Hi Salman, thanks a lot for jsperf.com/reegx-and-loop/10 - yes, that new perf test makes much more sense. The setup of functions should go into the preparation code.
– Axel Podehl
9 hours ago
|
show 3 more comments
My approach is similar to gnasher729, in that it uses the potential length of the substring as the main focus, but it is less math-y and process intensive:
L: Length of original string
S: Potential lengths of valid sub-strings
Loop S from (integer part of) L/2 to 1. If L/S is an integer check your original string against the fist S characters of the original string repeated L/S times.
The reason for looping from L/2 backwards and not from 1 onwards is to get the largest possible substring. If you want the smallest possible substring loop from 1 to L/2. Example: "abababab" has both "ab" and "abab" as possible substrings. Which of the two would be faster if you only care about a true/false result depends on the type of strings/substrings this will be applied to.
add a comment |
My approach is similar to gnasher729, in that it uses the potential length of the substring as the main focus, but it is less math-y and process intensive:
L: Length of original string
S: Potential lengths of valid sub-strings
Loop S from (integer part of) L/2 to 1. If L/S is an integer check your original string against the fist S characters of the original string repeated L/S times.
The reason for looping from L/2 backwards and not from 1 onwards is to get the largest possible substring. If you want the smallest possible substring loop from 1 to L/2. Example: "abababab" has both "ab" and "abab" as possible substrings. Which of the two would be faster if you only care about a true/false result depends on the type of strings/substrings this will be applied to.
add a comment |
My approach is similar to gnasher729, in that it uses the potential length of the substring as the main focus, but it is less math-y and process intensive:
L: Length of original string
S: Potential lengths of valid sub-strings
Loop S from (integer part of) L/2 to 1. If L/S is an integer check your original string against the fist S characters of the original string repeated L/S times.
The reason for looping from L/2 backwards and not from 1 onwards is to get the largest possible substring. If you want the smallest possible substring loop from 1 to L/2. Example: "abababab" has both "ab" and "abab" as possible substrings. Which of the two would be faster if you only care about a true/false result depends on the type of strings/substrings this will be applied to.
My approach is similar to gnasher729, in that it uses the potential length of the substring as the main focus, but it is less math-y and process intensive:
L: Length of original string
S: Potential lengths of valid sub-strings
Loop S from (integer part of) L/2 to 1. If L/S is an integer check your original string against the fist S characters of the original string repeated L/S times.
The reason for looping from L/2 backwards and not from 1 onwards is to get the largest possible substring. If you want the smallest possible substring loop from 1 to L/2. Example: "abababab" has both "ab" and "abab" as possible substrings. Which of the two would be faster if you only care about a true/false result depends on the type of strings/substrings this will be applied to.
edited 6 hours ago
answered 6 hours ago
SunKnight0SunKnight0
2,503167
2,503167
add a comment |
add a comment |
I read the answer of gnasher729 and implemented it.
The idea is that if there are any repetitions, then there must be (also) a prime number of repetitions. If you want performance, this is what you want.
function* primeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
function check (str) {
var n = str.length
primeloop:
for (p of primeFactors(n)) {
var l = n/p
var s = str.substring(0, l)
for (var j=1; j<p; j++) {
if (s != str.substring(l*j, l*(j+1))) continue primeloop
}
return true
}
return false
}
I've updated the jsPerf page that contains the algorithms used on this page.
add a comment |
I read the answer of gnasher729 and implemented it.
The idea is that if there are any repetitions, then there must be (also) a prime number of repetitions. If you want performance, this is what you want.
function* primeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
function check (str) {
var n = str.length
primeloop:
for (p of primeFactors(n)) {
var l = n/p
var s = str.substring(0, l)
for (var j=1; j<p; j++) {
if (s != str.substring(l*j, l*(j+1))) continue primeloop
}
return true
}
return false
}
I've updated the jsPerf page that contains the algorithms used on this page.
add a comment |
I read the answer of gnasher729 and implemented it.
The idea is that if there are any repetitions, then there must be (also) a prime number of repetitions. If you want performance, this is what you want.
function* primeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
function check (str) {
var n = str.length
primeloop:
for (p of primeFactors(n)) {
var l = n/p
var s = str.substring(0, l)
for (var j=1; j<p; j++) {
if (s != str.substring(l*j, l*(j+1))) continue primeloop
}
return true
}
return false
}
I've updated the jsPerf page that contains the algorithms used on this page.
I read the answer of gnasher729 and implemented it.
The idea is that if there are any repetitions, then there must be (also) a prime number of repetitions. If you want performance, this is what you want.
function* primeFactors (n) {
for (var k = 2; k*k <= n; k++) {
if (n % k == 0) {
yield k
do {n /= k} while (n % k == 0)
}
}
if (n > 1) yield n
}
function check (str) {
var n = str.length
primeloop:
for (p of primeFactors(n)) {
var l = n/p
var s = str.substring(0, l)
for (var j=1; j<p; j++) {
if (s != str.substring(l*j, l*(j+1))) continue primeloop
}
return true
}
return false
}
I've updated the jsPerf page that contains the algorithms used on this page.
answered 10 mins ago
user42723user42723
1304
1304
add a comment |
add a comment |
I'm not familiar with JavaScript, so I don't know how fast this is going to be, but here is a linear time solution (assuming reasonable builtin implementation) using only builtins. I'll describe the algorithm in pseudocode.
function check(str) {
t = str + str;
find all overlapping occurrences of str in t;
for each occurrence at position i
if (i > 0 && i < str.length && str.length % i == 0)
return true; // str is a repetition of its first i characters
return false;
}
The idea is similar to MBo's answer. For each i
that divides the length, str
is a repetition of its first i
characters if and only if it remains the same after shifting for i
characters.
It comes to my mind that such a builtin may be unavailable or inefficient. In this case, it is always possible to implement the KMP algorithm manually, which takes about the same amount of code as the algorithm in MBo's answer.
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its lengthi
,s[0:n-i] == s[i:n]
, or equivalently,s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?
– infmagic2047
57 mins ago
add a comment |
I'm not familiar with JavaScript, so I don't know how fast this is going to be, but here is a linear time solution (assuming reasonable builtin implementation) using only builtins. I'll describe the algorithm in pseudocode.
function check(str) {
t = str + str;
find all overlapping occurrences of str in t;
for each occurrence at position i
if (i > 0 && i < str.length && str.length % i == 0)
return true; // str is a repetition of its first i characters
return false;
}
The idea is similar to MBo's answer. For each i
that divides the length, str
is a repetition of its first i
characters if and only if it remains the same after shifting for i
characters.
It comes to my mind that such a builtin may be unavailable or inefficient. In this case, it is always possible to implement the KMP algorithm manually, which takes about the same amount of code as the algorithm in MBo's answer.
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its lengthi
,s[0:n-i] == s[i:n]
, or equivalently,s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?
– infmagic2047
57 mins ago
add a comment |
I'm not familiar with JavaScript, so I don't know how fast this is going to be, but here is a linear time solution (assuming reasonable builtin implementation) using only builtins. I'll describe the algorithm in pseudocode.
function check(str) {
t = str + str;
find all overlapping occurrences of str in t;
for each occurrence at position i
if (i > 0 && i < str.length && str.length % i == 0)
return true; // str is a repetition of its first i characters
return false;
}
The idea is similar to MBo's answer. For each i
that divides the length, str
is a repetition of its first i
characters if and only if it remains the same after shifting for i
characters.
It comes to my mind that such a builtin may be unavailable or inefficient. In this case, it is always possible to implement the KMP algorithm manually, which takes about the same amount of code as the algorithm in MBo's answer.
I'm not familiar with JavaScript, so I don't know how fast this is going to be, but here is a linear time solution (assuming reasonable builtin implementation) using only builtins. I'll describe the algorithm in pseudocode.
function check(str) {
t = str + str;
find all overlapping occurrences of str in t;
for each occurrence at position i
if (i > 0 && i < str.length && str.length % i == 0)
return true; // str is a repetition of its first i characters
return false;
}
The idea is similar to MBo's answer. For each i
that divides the length, str
is a repetition of its first i
characters if and only if it remains the same after shifting for i
characters.
It comes to my mind that such a builtin may be unavailable or inefficient. In this case, it is always possible to implement the KMP algorithm manually, which takes about the same amount of code as the algorithm in MBo's answer.
edited 14 hours ago
Peter Mortensen
14k1987114
14k1987114
answered 17 hours ago
infmagic2047infmagic2047
1347
1347
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its lengthi
,s[0:n-i] == s[i:n]
, or equivalently,s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?
– infmagic2047
57 mins ago
add a comment |
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its lengthi
,s[0:n-i] == s[i:n]
, or equivalently,s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?
– infmagic2047
57 mins ago
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
The OP wants to know whether repetition exists. The second line of (the body of) your function counts the number of repetitions - that's the bit that needs to be explained. E.g. "abcabcabc" has 3 repetitions of "abc", but how did your second line work out whether it had any repetitions?
– Lawrence
13 hours ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its length
i
, s[0:n-i] == s[i:n]
, or equivalently, s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?– infmagic2047
57 mins ago
@Lawrence I don't understand your question. This algorithm is based on the idea that the string is a repetition of its substring if and only if for some divisor of its length
i
, s[0:n-i] == s[i:n]
, or equivalently, s == s[i:n] + s[0:i]
. Why does the second line need to work out whether it had any repetitions?– infmagic2047
57 mins ago
add a comment |
One of the simple ideas is to replace the string with the substring of "" and if any text exist then it is false, else it is true.
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
4
What aboutabcabcabc
orunicornunicorn
?
– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
add a comment |
One of the simple ideas is to replace the string with the substring of "" and if any text exist then it is false, else it is true.
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
4
What aboutabcabcabc
orunicornunicorn
?
– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
add a comment |
One of the simple ideas is to replace the string with the substring of "" and if any text exist then it is false, else it is true.
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
One of the simple ideas is to replace the string with the substring of "" and if any text exist then it is false, else it is true.
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
""// return true
edited 14 hours ago
Peter Mortensen
14k1987114
14k1987114
answered 19 hours ago
Vinod kumar GVinod kumar G
423412
423412
4
What aboutabcabcabc
orunicornunicorn
?
– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
add a comment |
4
What aboutabcabcabc
orunicornunicorn
?
– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
4
4
What about
abcabcabc
or unicornunicorn
?– adiga
19 hours ago
What about
abcabcabc
or unicornunicorn
?– adiga
19 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
yes, for abc or unicorn wouldn't user will check with /abc/ or /unicorn/ , sorry if i am missing your context
– Vinod kumar G
17 hours ago
1
1
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
The question could be clearer, but what it's asking for is a way of deciding whether the string is completely made up of 2 or more repetitions of any other string. It is not searching for a specific substring.
– HappyDog
16 hours ago
1
1
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
I've added some clarification to the question, which should make it clearer now.
– HappyDog
15 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
@Vinod if you are already going to use regex you should anchor your match and use test. No reason to modify the string just to validate some condition.
– Marie
13 hours ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55823298%2fhow-do-i-check-if-a-string-is-entirely-made-of-the-same-substring%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
6
This link may be useful to you. I always find geekforgeeks as a good source for algorithm problems - geeksforgeeks.org/…
– Leron
19 hours ago
I think its a problem of checking whether a common substring occurs throughout uniformly
– Kunal Mukherjee
18 hours ago
1
Do you mind if I borrow this and make it a coding challenge on the Programming Golf exchange site?
– ouflak
10 hours ago
@ouflak you can do that.
– Maheer Ali
10 hours ago
In case your curious, codegolf.stackexchange.com/questions/184682/…
– ouflak
10 hours ago