[解決済み] 文字列がすべて同じ部分文字列で構成されているかどうかを調べるにはどうすればよいですか?
質問
文字列を受け取る関数を作成する必要があります。
true
または
false
は、入力が繰り返される文字列から構成されているかどうかに 基づいています。与えられた文字列の長さは,常に
1
よりも大きく、文字列は少なくとも1つの繰り返しを持たなければなりません。
"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)
以下のような関数を作りました。
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
これをチェックすることが、本当の問題の一部なのです。こんな非効率的な解決策は許されない。まず、文字列の半分をループしている。
第二の問題は、それが
replace()
を使用しているため、動作が遅くなります。パフォーマンスに関してより良い解決策はあるのでしょうか?
どのように解決するのですか?
このような文字列には気の利いた定理があるのです。
文字列がそれ自身の非自明な回転である場合に限り、文字列は同じパターンを複数回繰り返すことで構成される。
ここで回転とは、文字列の前方からある数の文字を削除し、後方に移動させることを意味する。例えば、文字列
hello
という文字列は、回転してこれらの文字列のいずれかになります。
hello (the trivial rotation)
elloh
llohe
lohel
ohell
なぜこれがうまくいくかというと、まず、文字列がある文字列wのk個の繰り返しコピーからできていると仮定すると、文字列の前から繰り返しパターン(w)の最初のコピーを削除し、後ろに張り付けると同じ文字列が戻ってきます。逆方向は証明するのが少し難しいですが、文字列を回転させて最初のものを取り戻すと、その回転を繰り返し適用して、同じパターンの複数のコピーで文字列をタイル状にすることができるということです (そのパターンは、回転を行うために端に移動する必要があった文字列です)。
さて、問題はこれが事実であるかどうかをどのように確認するかです。そのために、もう一つ使える美しい定理があります。
xとyが同じ長さの文字列であるとき、xがyyの部分文字列であるときのみ、xはyの回転である。
例として、以下のようになります。
lohel
の回転であることがわかります。
hello
を以下のように回転させる。
hellohello
^^^^^
この場合、すべての文字列xは常にxxの部分文字列であることが分かっている(xの各コピーで1回ずつ、2回現れる)。ですから、基本的には、文字列xがxxの部分文字列であるかどうかを、最初の文字や途中の文字でマッチしないようにチェックすればよいのです。以下はそのためのワンライナーです。
function check(str) {
return (str + str).indexOf(str, 1) !== str.length;
}
仮定の話
indexOf
が高速な文字列マッチングアルゴリズムを用いて実装されている場合、これは時間O(n)で実行されます(nは入力文字列の長さ)。
これが役に立つことを願っています。
関連
-
[解決済み] jQueryで要素が非表示になっているかどうかを確認するには?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Bashで文字列が部分文字列を含むかどうかをチェックする方法
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】jQueryでチェックボックスがチェックされているかどうかを確認するにはどうすればよいですか?
-
[解決済み] 兄弟ノードを選択する方法はありますか?
-
[解決済み] async-await from functionを使用して非同期関数から値を返すには?重複
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】面接の質問です。ある文字列が他の文字列の回転であるかどうかのチェック [終了しました]
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] reactのrender関数でdynamic hrefを作成するには?
-
[解決済み] URL/アドレスバーからJavascriptの関数を呼び出す
-
[解決済み] Chart.jsを使ってドーナツチャートの中にテキストを追加するには?
-
[解決済み] 兄弟ノードを選択する方法はありますか?
-
[解決済み] JavaScriptでクエリ文字列が存在するかどうかを確認するには?
-
[解決済み] リアクトのシャローコンパールはどのように機能するのか
-
[解決済み] jQueryを使って、ターゲット要素のクリック座標を取得する方法
-
[解決済み] Chrome DevToolsでソースマップを無効にする