Làm cách nào để kiểm tra xem một chuỗi hoàn toàn được tạo từ cùng một chuỗi con?


128

Tôi phải tạo một hàm lấy một chuỗi và nó sẽ trả về truehoặc falsedựa trên việc đầu vào có bao gồm một chuỗi ký tự lặp lại hay không. Độ dài của chuỗi đã cho luôn lớn hơn 1và chuỗi ký tự phải có ít nhất một lần lặp lại.

"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)

Tôi đã tạo ra các chức năng dưới đây:

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

Kiểm tra điều này là một phần của vấn đề thực sự. Tôi không thể mua một giải pháp không hiệu quả như thế này. Trước hết, nó lặp qua một nửa chuỗi.

Vấn đề thứ hai là nó đang sử dụng replace()trong mỗi vòng lặp làm cho nó chậm. Có một giải pháp tốt hơn về hiệu suất?


19
Liên kết này có thể hữu ích cho bạn. Tôi luôn thấy geekforgeek là một nguồn tốt cho các vấn đề thuật toán - geekforgeek.org/,
Leron_says_get_back_Monica

9
Bạn có phiền nếu tôi mượn cái này và biến nó thành một thách thức mã hóa trên trang web trao đổi Lập trình Golf không?
ngerak

7
@urdyak bạn có thể làm điều đó.
Maheer Ali

12
Trong trường hợp bạn tò mò, codegolf.stackexchange.com/questions/184682/iêu
sakeak

24
@Shidersz Sử dụng mạng thần kinh cho việc này có cảm giác hơi giống như sử dụng súng thần công để bắn muỗi.
JAD

Câu trả lời:


186

Có một định lý nhỏ tiện lợi về các chuỗi như thế này.

Một chuỗi bao gồm cùng một mẫu được lặp lại nhiều lần khi và chỉ khi chuỗi đó là một vòng quay không cần thiết của chính nó.

Ở đây, xoay có nghĩa là xóa một số ký tự từ phía trước chuỗi và di chuyển chúng ra phía sau. Ví dụ: chuỗi hellocó thể được xoay để tạo thành bất kỳ chuỗi nào trong số này:

hello (the trivial rotation)
elloh 
llohe 
lohel 
ohell 

Để xem tại sao điều này hoạt động, trước tiên, giả sử rằng một chuỗi bao gồm k bản sao lặp lại của một chuỗi w. Sau đó xóa bản sao đầu tiên của mẫu lặp lại (w) từ phía trước của chuỗi và xử lý nó ở phía sau sẽ trả lại cùng một chuỗi. Hướng ngược lại khó hơn một chút để chứng minh, nhưng ý tưởng là nếu bạn xoay một chuỗi và lấy lại những gì bạn đã bắt đầu, bạn có thể áp dụng xoay vòng đó nhiều lần để xếp chuỗi với nhiều bản sao của cùng một mẫu (mẫu đó là chuỗi bạn cần di chuyển đến cuối để thực hiện xoay vòng).

Bây giờ câu hỏi là làm thế nào để kiểm tra xem đây là trường hợp. Vì thế, có một định lý hay khác mà chúng ta có thể sử dụng:

Nếu x và y là các chuỗi có cùng độ dài thì x là một phép quay của y khi và chỉ khi x là một chuỗi con của yy.

Ví dụ, chúng ta có thể thấy đó lohellà một vòng quay hellonhư sau:

hellohello
   ^^^^^

Trong trường hợp của chúng tôi, chúng tôi biết rằng mọi chuỗi x sẽ luôn là một chuỗi con của xx (nó sẽ xuất hiện hai lần, một lần tại mỗi bản sao của x). Vì vậy, về cơ bản chúng ta chỉ cần kiểm tra xem chuỗi x của chúng ta có phải là chuỗi con của xx mà không cho phép nó khớp với ký tự đầu tiên hoặc nửa chừng. Đây là một lớp lót cho điều đó:

function check(str) {
    return (str + str).indexOf(str, 1) !== str.length;
}

Giả sử indexOfđược thực hiện bằng thuật toán khớp chuỗi nhanh, điều này sẽ chạy trong thời gian O (n), trong đó n là độ dài của chuỗi đầu vào.

Hi vọng điêu nay co ich!


13
Rất đẹp! Tôi đã thêm nó vào trang chuẩn jsPerf .
dùng42723

10
@ user42723 Tuyệt! Có vẻ như nó thực sự, rất nhanh.
templatetypedef

5
FYI: Tôi đã có một thời gian khó tin vào câu đó cho đến khi tôi đảo ngược từ ngữ: "Một chuỗi là một vòng quay không cần thiết của chính nó nếu và chỉ khi nó bao gồm cùng một mẫu lặp đi lặp lại nhiều lần". Đi hình.
Axel Podehl

11
Bạn có tài liệu tham khảo cho các định lý?
HRK44

4
Tôi nghĩ rằng câu lệnh đầu tiên giống như " Bổ đề 2.3 : Nếu x và góc quay của x bằng nhau, thì x là sự lặp lại" tại doi.org/10.1016/j.tcs.2008.04.020 . Xem thêm: stackoverflow.com/a/2553533/1462295
BurnsBA

67

Bạn có thể làm điều đó bởi một nhóm chụpbackreference . Chỉ cần kiểm tra xem đó là sự lặp lại của giá trị được bắt đầu tiên.

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

Trong RegExp ở trên:

  1. ^$là viết tắt của neo bắt đầu và kết thúc để dự đoán vị trí.
  2. (.+)chụp bất kỳ mẫu nào và chụp giá trị (ngoại trừ \n).
  3. \1là phản hồi của giá trị bị bắt đầu tiên và \1+sẽ kiểm tra sự lặp lại của giá trị đã bắt.

Regex giải thích ở đây

Để sử dụng gỡ lỗi RegExp: https://regex101.com/r/pqlAuP/1/debugger

Hiệu suất: https://jsperf.com/reegx-and-loop/13


2
Bạn có thể giải thích cho chúng tôi những gì dòng này đang thực hiện trở lại / ^ (. +) \ 1+$ /.test (str)
Thanveer Shah

34
Ngoài ra sự phức tạp của giải pháp này là gì? Tôi không hoàn toàn chắc chắn nhưng dường như nó không nhanh hơn nhiều so với OP.
Leron_says_get_back_Monica

8
@PranavCBalan Tôi không giỏi về thuật toán, đó là lý do tại sao tôi viết trong phần bình luận. Tuy nhiên tôi có một vài điều cần đề cập - OP đã có một giải pháp hoạt động nên anh ấy đang yêu cầu một giải pháp sẽ mang lại cho anh ấy hiệu suất tốt hơn và bạn chưa giải thích cách giải pháp của bạn sẽ vượt trội hơn anh ấy. Ngắn hơn không có nghĩa là nhanh hơn. Ngoài ra, từ liên kết bạn đã đưa ra: If you use normal (TCS:no backreference, concatenation,alternation,Kleene star) regexp and regexp is already compiled then it's O(n).nhưng như bạn đã viết, bạn đang sử dụng phản hồi vì vậy nó vẫn là O (n)?
Leron_says_get_back_Monica

5
Bạn có thể sử dụng [\s\S]thay vì .nếu bạn cần khớp các ký tự dòng mới theo cách tương tự như các ký tự khác. Ký tự dấu chấm không khớp trên dòng mới; các tìm kiếm thay thế cho tất cả các ký tự khoảng trắng và không trắng, có nghĩa là các dòng mới được đưa vào trận đấu. (Lưu ý rằng điều này nhanh hơn trực quan hơn (.|[\r\n]).) Tuy nhiên, nếu chuỗi chắc chắn không chứa dòng mới, thì đơn giản .sẽ nhanh nhất. Lưu ý điều này sẽ đơn giản hơn rất nhiều nếu cờ dotall được thực hiện.
HappyDog

2
Không /^(.+?)\1+$/nhanh hơn một chút sao? (12 bước so với 20 bước)
trực tuyến Thomas

29

Có lẽ cách tiếp cận thuật toán nhanh nhất là xây dựng hàm Z trong thời gian tuyến tính:

Hàm Z ​​cho chuỗi này là một mảng có độ dài n trong đó phần tử thứ i bằng số ký tự lớn nhất bắt đầu từ vị trí i trùng với các ký tự đầu tiên của s.

Nói cách khác, z [i] là độ dài của tiền tố chung dài nhất giữa s và hậu tố của s bắt đầu từ i.

Triển khai C ++ để tham khảo:

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;
}

Triển khai JavaScript
Đã thêm tối ưu hóa - xây dựng một nửa mảng z và thoát sớm

function z_function(s) {
  var n = s.length;
  var z = Array(n).fill(0);
  var i, l, r;
  //for our task we need only a half of z-array
  for (i = 1, l = 0, r = 0; i <= n/2; ++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 false; 
  //return z.some((zi, i) => (i + zi) === n && n % i === 0);
}
console.log(z_function("abacabacabac"));
console.log(z_function("abcab"));

Sau đó, bạn cần kiểm tra các chỉ số ichia n. Nếu bạn thấy như vậy ii+z[i]=nsau đó các chuỗi scó thể được nén đến độ dài ivà bạn có thể trở lại true.

Ví dụ:

string s= 'abacabacabac'  with length n=12`

mảng z là

(0, 0, 1, 0, 8, 0, 1, 0, 4, 0, 1, 0)

và chúng ta có thể tìm thấy điều đó cho

i=4
i+z[i] = 4 + 8 = 12 = n
and
n % i = 12 % 4 = 0`

do đó scó thể được biểu diễn dưới dạng chuỗi con có độ dài 4 được lặp lại ba lần.


3
return z.some((zi, i) => (i + zi) === n && n % i === 0)
Pranav C Balan

2
Cảm ơn bạn đã thêm nội dung JavaScript vào Salman A và Pranav C Balan
MBo

1
Cách tiếp cận khác bằng cách tránh lặp lại bổ sungconst 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

2
Sử dụng chức năng z là một ý tưởng tốt, nhưng đó là 'thông tin đầy đủ', nó chứa rất nhiều thông tin không bao giờ được sử dụng.
Axel Podehl

@Axel Podehl Tuy nhiên, nó xử lý chuỗi trong thời gian O (n) (mỗi char được sử dụng nhiều nhất hai lần). Trong mọi trường hợp, chúng ta phải kiểm tra mọi char, vì vậy không có thuật toán nào nhanh hơn về mặt lý thuyết (trong khi các phương thức được xây dựng tối ưu hóa có thể vượt trội hơn). Ngoài ra trong lần chỉnh sửa cuối cùng, tôi đã giới hạn tính toán bằng 1/2 độ dài chuỗi.
MBo

23

Tôi đọc câu trả lời của gnasher729 và thực hiện nó. Ý tưởng là nếu có bất kỳ sự lặp lại nào, thì phải có (cũng) một số lần lặp lại chính.

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 (var 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
}

Một thuật toán hơi khác là đây:

function check (str) {
    var n = str.length
    for (var p of primeFactors(n)) {
        var l = n/p
        if (str.substring(0, n-l) == str.substring(l)) return true
    }
    return false
}

Tôi đã cập nhật trang jsPerf có chứa các thuật toán được sử dụng trên trang này.


Điều này có vẻ thực sự nhanh chóng vì nó bỏ qua kiểm tra không cần thiết.
Pranav C Balan

1
Rất đẹp, chỉ tôi nghĩ rằng tôi sẽ kiểm tra xem chữ cái đầu tiên xuất hiện lại ở vị trí đã chỉ định trước khi thực hiện các cuộc gọi chuỗi con.
Ben Voigt

Đối với những người function*lần đầu tiên vấp ngã như tôi, đó là để khai báo một trình tạo, không phải là một chức năng thông thường. Xem MDN
Julien Rousé

17

Giả sử chuỗi S có độ dài N và được tạo thành từ các bản sao của chuỗi con s, thì độ dài của s chia N. Ví dụ: nếu S có độ dài 15, thì chuỗi con có độ dài 1, 3 hoặc 5.

Đặt S được tạo thành từ (p * q) bản sao của s. Sau đó S cũng được tạo thành từ p bản sao của (s, lặp lại q lần). Do đó, chúng ta có hai trường hợp: Nếu N là số nguyên tố hoặc 1, thì S chỉ có thể được tạo thành các bản sao của chuỗi con có độ dài 1. Nếu N là hợp số, thì chúng ta chỉ cần kiểm tra các chuỗi con có độ dài N / p để phân chia số nguyên tố p chiều dài của S.

Vì vậy, xác định N = độ dài của S, sau đó tìm tất cả các thừa số nguyên tố của nó trong thời gian O (sqrt (N)). Nếu chỉ có một yếu tố N, hãy kiểm tra xem S có phải là chuỗi lặp lại N lần không, nếu không, với mỗi yếu tố nguyên tố p, hãy kiểm tra xem S có bao gồm p lặp lại của các ký tự N / p đầu tiên không.


Tôi đã không kiểm tra các giải pháp khác, nhưng điều này có vẻ rất nhanh. Bạn có thể bỏ qua phần "Nếu chỉ có một yếu tố N, hãy kiểm tra ..., nếu không" để đơn giản, vì đây không phải là trường hợp đặc biệt. Sẽ rất tuyệt khi thấy một triển khai Javascript có thể được chạy trong jsPerf bên cạnh các triển khai khác.
dùng42723

1
Bây giờ tôi đã thực hiện điều này trong câu trả lời của mình
user42723

10

Tôi nghĩ rằng một chức năng đệ quy cũng có thể rất nhanh. Quan sát đầu tiên là chiều dài mẫu lặp lại tối đa bằng một nửa so với tổng chuỗi. Và chúng tôi chỉ có thể kiểm tra tất cả các độ dài mẫu lặp lại có thể có: 1, 2, 3, ..., str.length / 2

Hàm đệ quy isRepeat (p, str) kiểm tra nếu mẫu này được lặp lại trong str.

Nếu str dài hơn mẫu, đệ quy yêu cầu phần đầu tiên (cùng độ dài với p) là phần lặp lại cũng như phần còn lại của str. Vì vậy, str được chia thành các phần có chiều dài p.length một cách hiệu quả.

Nếu mẫu và str được thử nghiệm có kích thước bằng nhau, đệ quy kết thúc tại đây, thành công.

Nếu độ dài khác nhau (xảy ra đối với "aba" và mẫu "ab") hoặc nếu các mảnh khác nhau, thì sai được trả về, truyền lên đệ quy.

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

Hiệu suất: https://jsperf.com/reegx-and-loop/13


1
Nó sẽ nhanh hơn để kiểm tra if( str===p.repeat(str.length/i) ) return true;thay vì sử dụng một hàm đệ quy?
Chronocidal

1
Không đặt console.logs trong các bài kiểm tra jsperf, chuẩn bị các chức năng bên trong phần toàn cầu, cũng chuẩn bị các chuỗi kiểm tra trong phần toàn cầu (xin lỗi, không thể chỉnh sửa jsperf)
Salman A

@Salman - điểm tốt. Tôi vừa sửa đổi jsperf từ người tiền nhiệm (Pranav C), lần đầu tiên tôi sử dụng jsperf, công cụ tuyệt vời.
Axel Podehl

@SalmanA: đã cập nhật: jsperf.com/regex-and-loop/1 ... cảm ơn vì thông tin ... thậm chí tôi không quen với nó (Jsperf) ... cảm ơn vì thông tin
Pranav C Balan

Xin chào Salman, cảm ơn rất nhiều về jsperf.com/reegx-and-loop/10 - vâng, bài kiểm tra hoàn hảo mới này có ý nghĩa hơn nhiều. Việc thiết lập các chức năng nên đi vào mã chuẩn bị.
Axel Podehl

7

Đã viết điều này trong Python. Tôi biết nó không phải là nền tảng, nhưng nó đã mất 30 phút thời gian. PS => PYTHON

def checkString(string):
    gap = 1 
    index= 0
    while index < len(string)/2:
        value  = [string[i:i+gap] for i in range(0,len(string),gap) ]

        x = [string[:gap]==eachVal for eachVal in value]

        if all(x):
            print("THEY ARE  EQUAL")
            break 

        gap = gap+1
        index= index+1 

checkString("aaeaaeaaeaae")

6

Cách tiếp cận của tôi tương tự như gnasher729, ở chỗ nó sử dụng độ dài tiềm năng của chuỗi con làm trọng tâm chính, nhưng nó ít toán học hơn và xử lý chuyên sâu:

L: Độ dài của chuỗi gốc

S: Độ dài tiềm năng của chuỗi con hợp lệ

Vòng lặp S từ (phần nguyên của) L / 2 đến 1. Nếu L / S là số nguyên kiểm tra chuỗi gốc của bạn so với các ký tự S đầu tiên của chuỗi gốc lặp lại L / S lần.

Lý do lặp từ L / 2 trở đi và không từ 1 trở đi là để có được chuỗi con lớn nhất có thể. Nếu bạn muốn vòng lặp chuỗi con nhỏ nhất có thể từ 1 đến L / 2. Ví dụ: "abababab" có cả "ab" và "abab" như các chuỗi con có thể. Cái nào trong hai cái sẽ nhanh hơn nếu bạn chỉ quan tâm đến kết quả đúng / sai phụ thuộc vào loại chuỗi / chuỗi con mà nó sẽ được áp dụng.


5

Mã Mathicala sau đây gần như phát hiện nếu danh sách được lặp lại ít nhất một lần. Nếu chuỗi được lặp lại ít nhất một lần, nó sẽ trả về true, nhưng nó cũng có thể trả về true nếu chuỗi là tổ hợp tuyến tính của các chuỗi lặp lại.

IsRepeatedQ[list_] := Module[{n = Length@list},
   Round@N@Sum[list[[i]] Exp[2 Pi I i/n], {i, n}] == 0
];

Mã này tìm kiếm sự đóng góp "toàn thời gian", phải bằng 0 trong một chuỗi lặp lại, nhưng chuỗi accbbdcũng được coi là lặp lại, vì nó là tổng của hai chuỗi lặp lại ababab012012 .

Ý tưởng là sử dụng Biến đổi Fourier nhanh và tìm kiếm phổ tần số. Bằng cách nhìn vào các tần số khác, người ta cũng có thể phát hiện ra kịch bản kỳ lạ này.


4

Ý tưởng cơ bản ở đây là kiểm tra bất kỳ chuỗi con tiềm năng nào, bắt đầu ở độ dài 1 và dừng ở một nửa độ dài của chuỗi ban đầu. Chúng tôi chỉ xem xét độ dài chuỗi con chia đều chiều dài chuỗi gốc (ví dụ: str.length% sub chuỗi.length == 0).

Việc thực hiện này xem xét ký tự đầu tiên của mỗi lần lặp chuỗi con có thể trước khi chuyển sang ký tự thứ hai, điều này có thể tiết kiệm thời gian nếu các chuỗi con dự kiến ​​sẽ dài. Nếu không tìm thấy sự không phù hợp sau khi kiểm tra toàn bộ chuỗi con, thì chúng ta trả về đúng.

Chúng tôi trả về false khi chúng tôi hết các chuỗi con tiềm năng để kiểm tra.

function check(str) {
  const len = str.length;
  for (let subl = 1; subl <= len/2; ++subl) {
    if ((len % subl != 0) || str[0] != str[subl])
      continue;
    
    let i = 1;
    for (; i < subl; ++i)
    {
      let j = 0;
      for (; j < len; j += subl)
        if (str[i] != str[j + i])
          break;
      if (j != len)
        break;
    }
    
    if (i == subl)
      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


-1

Tôi không quen thuộc với JavaScript, vì vậy tôi không biết điều này sẽ diễn ra nhanh như thế nào, nhưng đây là một giải pháp thời gian tuyến tính (giả sử triển khai dựng sẵn hợp lý) chỉ sử dụng nội dung. Tôi sẽ mô tả thuật toán trong mã giả.

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;
}

Ý tưởng tương tự như câu trả lời của MBo. Đối với mỗi iphân chia độ dài, strlà sự lặp lại của các iký tự đầu tiên của nó khi và chỉ khi nó giữ nguyên sau khi thay đổi các iký tự.

Tôi nghĩ rằng một nội dung như vậy có thể không có sẵn hoặc không hiệu quả. Trong trường hợp này, luôn có thể thực hiện thuật toán KMP theo cách thủ công, thuật toán này có cùng số lượng mã như thuật toán trong câu trả lời của MBo.


OP muốn biết liệu sự lặp lại có tồn tại hay không . Dòng thứ hai của (phần thân) hàm của bạn đếm số lần lặp lại - đó là bit cần được giải thích. Ví dụ: "abcabcabc" có 3 lần lặp lại "abc", nhưng dòng thứ hai của bạn hoạt động như thế nào cho dù nó có bất kỳ sự lặp lại?
Lawrence

@Lawrence Tôi không hiểu câu hỏi của bạn. Thuật toán này được dựa trên ý tưởng rằng chuỗi là một sự lặp lại của chuỗi con của nó khi và chỉ khi đối với một số ước của chiều dài của nó i, s[0:n-i] == s[i:n]hoặc tương đương, s == s[i:n] + s[0:i]. Tại sao dòng thứ hai cần phải tìm ra liệu nó có bất kỳ sự lặp lại?
infmagic2047

Hãy để tôi xem nếu tôi hiểu thuật toán của bạn. Đầu tiên, bạn nối strvào chính nó để hình thành t, sau đó quét tđể cố gắng tìm strbên trong t. Được rồi, điều này có thể hoạt động (Tôi đã rút lại downvote của mình). Nó không phải là tuyến tính trong strlen (str), mặc dù. Say strcó độ dài L. Sau đó, tại mỗi vị trí p = 0,1,2, ..., kiểm tra xem str [0..L-1] == t [p..p + L-1] có O (L ) thời gian. Bạn cần thực hiện kiểm tra O (L) khi bạn đi qua các giá trị của p, vì vậy đó là O (L ^ 2).
Lawrence

-10

Một trong những ý tưởng đơn giản là thay thế chuỗi bằng chuỗi con "" và nếu có bất kỳ văn bản nào tồn tại thì đó là sai, nếu không nó là đúng.

'ababababa'.replace(/ab/gi,'')
"a" // return false
'abababab'.replace(/ab/gi,'')
 ""// return true


có, đối với abc hoặc kỳ lân, người dùng sẽ không kiểm tra với / abc / hoặc / unicorn /, xin lỗi nếu tôi thiếu ngữ cảnh của bạn
Vinod kumar G

3
Câu hỏi có thể rõ ràng hơn, nhưng những gì nó yêu cầu là một cách để quyết định xem chuỗi có hoàn toàn được tạo thành từ 2 hoặc nhiều lần lặp lại của bất kỳ chuỗi nào khác hay không. Nó không tìm kiếm một chuỗi con cụ thể.
HappyDog

2
Tôi đã thêm một số làm rõ cho câu hỏi, điều này sẽ làm cho nó rõ ràng hơn bây giờ.
HappyDog

@Vinod nếu bạn đã sử dụng regex, bạn nên neo trận đấu của mình và sử dụng thử nghiệm. Không có lý do để sửa đổi chuỗi chỉ để xác nhận một số điều kiện.
Marie
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.