を私は何を理解していません「繰り返しの文字を格納することはできません」という意味です。ハッシュセットはSet
なので、2つのことができます。値を追加したり、値を追加したりできます。この場合、問題は文字列ではなく文字列をHashSetに格納して質問に答えることを望みます。 Javaでこれを行うには:
Set<String> stringSet = new HashSet<String>();
は二つの部分にこの問題を破壊してみてください。 1は、この問題を解決するために、文字列 2.の長さlen
のすべての部分文字列を生成します。
部2のヒントがある: ステップ1:最初の文字列の場合HashSetの ステップ2にサブストリングを入力します。この:2番目の文字列については、HashSetの
注(高度)の値をチェック問題はあまり指定されていません。ハッシュテーブルに文字列を入力してチェックするのは、文字列の長さです。長さnの文字列aには、長さkのO(n-k)個の部分文字列があります。だからstring a
は長さがn
の文字列で、文字列bは長さがm
の文字列ですO((n-k)*k+(m-k)*k)
これはk = n/2の実行時間がO((n/2)*であるため、 N/2))= O(N^2)
編集:だから、あなたが実際にO(n)
(あるいはO(n+m+k)
でこれを行うために何をしたい場合)?私の考えは、元の宿題が上記のアルゴリズムのようなものを求めていたことです。しかし、私たちはより良くすることができます。さらに、私たちはもっとうまくやっても、HashSet
をアルゴリズムの重要なツールにすることができます。このアイデアは、 "Rolling Hash"を使って検索を実行することです。 Wikipediaはカップルについて説明しています:http://en.wikipedia.org/wiki/Rolling_hashでも、私たちは自分自身を実装します。
簡単な解決策を一緒にハッシュ文字の値をXORすることであろう。これにより、新しい文字をハッシュO(1)
に追加し、O(1)
を削除して次のハッシュを計算しやすくすることができます。しかし、この単純なアルゴリズムは2つの理由で機能しません。
- 文字ハッシュは十分なエントロピーを提供しません。さて、私たちがこの問題を抱えているかどうかはわかりませんが、とにかく楽しいために解決してください。
- 私たちは、同じ値に順列をハッシュしますが...「ABC」
たちはAIからのアイデアを使用することができます最初の問題を解決するには、「CBA」と同じハッシュを持つべきではない、すなわちから鋼をすることができますZobrist hashing。考えられるすべての文字に、より大きな長さのランダムな値を割り当てることです。 ASCIを使用していた場合、すべてのASCI文字を含む配列を簡単に作成できますが、Unicode文字を使用すると問題が発生します。代わりに値を遅延的に割り当てることです。
object LazyCharHash{
private val map = HashMap.empty[Char,Int]
private val r = new Random
def lHash(c: Char): Int = {
val d = map.get(c)
d match {
case None => {
map.put(c,r.nextInt)
lHash(c)
}
case Some(v) => v
}
}
}
これはScalaコードです。 ScalaはJavaよりもあまり冗長ではありませんが、Javaコレクションを使用できるようになりました。そのため、命令型のScalaを使用していきます。翻訳が難しいことではありません。
第二の問題は、aswellを解決することができます。まず、代わりに純粋なXORを使用して、我々はこのようにハッシュ関数は今、シフトで私たちのXORを組み合わせ:のコース
def fullHash(s: String) = {
var h = 0
for(i <- 0 until s.length){
h = h >>> 1
h = h^LazyCharHash.lHash(s.charAt(i))
}
h
}
、文句を言わないパフォーマンス上の利点を与えるfullHash
を使用します。それは、私たちは(私たちはそれを使用すると約束)HashSet
に値を格納するために、当社のハッシュ関数を使用する方法を必要なだけの仕様
です。私達はちょうどラッパークラスを作成することができます。
class HString(hash: Int, string: String){
def getHash = hash
def getString = string
override def equals(otherHString: Any): Boolean = {
otherHString match {
case other: HString => (hash == other.getHash) && (string == other.getString)
case _ => false
}
}
override def hashCode = hash
}
オーケーを、ハッシュ関数のローリングを作るために、私達はちょうど私たちはもはや使用される文字に関連付けられた値をXORする必要があります。それには、その価値を適切な額だけシフトさせるだけです。
def stringIntersect(a: String, b: String, len: Int): Boolean = {
val stringSet = new HashSet[HString]()
var h = 0
for(i <- 0 until len){
h = h >>> 1
h = h^LazyCharHash.lHash(a.charAt(i))
}
stringSet.add(new HString(h,a.substring(0,len)))
for(i <- len until a.length){
h = h >>> 1
h = h^(LazyCharHash.lHash(a.charAt(i - len)) >>> (len))
h = h^LazyCharHash.lHash(a.charAt(i))
stringSet.add(new HString(h,a.substring(i - len + 1,i + 1)))
}
...
このコードを自分で完成させる方法を知ることができます。
このO(n)
ですか?まあ、それは何を意味するのか。ビッグオハイオ州、ビッグオメガ、ビッグシータ、すべての境界線のメトリックです。アルゴリズムの最悪の場合、最良の場合、または何か他のもののメトリックとして役立つ可能性があります。この場合、これらの変更は、がO(n)
パフォーマンスが期待できますが、我々はハッシュの衝突を避ける場合にのみ成立します。 2つの文字列が等しいかどうかを調べるにはまだO(n)
が必要です。このランダムアプローチはうまくいきますし、ランダムビット配列のサイズを拡大してよりうまくいくようにすることもできますが、パフォーマンスは保証されていません。
あなたは「文字を繰り返して保存することができない」とはどういう意味ですか? – user802421
私は誤って、2つの文字列を1組の文字として格納することになっていると思っていました。例えば、私がhooplaを文字セットとして保存したいのであれば、両方の "o"を保存することはできませんでした。しかし、文字列を格納するべきではなく、代わりに部分文字列を格納すべきであることを認識しています。 –