Skip to content

Commit cb17753

Browse files
committed
leetcode 29. Divide Two Integers 整数除算を行う関数(乗算、除算、剰余演算子を使わない)
1 parent 770f0d3 commit cb17753

7 files changed

Lines changed: 868 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
了解しました。以下では、問題「**最長の重複部分文字列の長さを求める**」について、**Pythonコードに基づいて各処理を図解・詳細に解析**します。以下の4ステップに分けて説明します。
2+
3+
---
4+
5+
## 🎯 問題の要点
6+
7+
与えられた文字列 `S` において、**2つ以上の位置で一致する部分文字列が存在する長さ `k` の最大値**を求める。
8+
9+
---
10+
11+
## ✅ 全体構成(処理の流れ)
12+
13+
```text
14+
入力: N, S
15+
16+
17+
┌─────────────────────┐
18+
│ 二分探索で長さ k を探索 │ ← k の候補は 0〜N-1
19+
└─────────────────────┘
20+
21+
22+
┌────────────────────┐
23+
│ ローリングハッシュで │
24+
│ 長さ k の部分文字列に │
25+
│ 重複があるかをチェック │
26+
└────────────────────┘
27+
28+
29+
最大値を出力
30+
```
31+
32+
---
33+
34+
## 🔍 詳細解析①:**ローリングハッシュの考え方**
35+
36+
### 🔸目的
37+
38+
文字列の部分列の比較を **定数時間** で行うために、**数値のようにハッシュ値を使って比較**します。
39+
40+
### 🔸イメージ図
41+
42+
例えば、文字列 `S = "NANANANANA"` に対して長さ `k = 3` の部分列をチェックする場合:
43+
44+
```
45+
S = N A N A N A N A N A
46+
└───┘
47+
48+
"NAN" を数値で表現 → ハッシュ値
49+
```
50+
51+
各部分列 `"NAN"`, `"ANA"`, `"NAN"`, ... について、ハッシュ値を計算して **すでに出現したハッシュ値があるかを調べる**
52+
53+
---
54+
55+
## 🔍 詳細解析②:**`compute_hash()` の処理**
56+
57+
関数 `compute_hash(s, length)` は、**長さ `length` の重複部分文字列が存在するか**をチェックする関数です。
58+
59+
### 🧮 ハッシュ計算の式
60+
61+
与えられた部分文字列 `s[i..i+length-1]` のハッシュ値は:
62+
63+
```
64+
H = s[i] * B^(k-1) + s[i+1] * B^(k-2) + ... + s[i+k-1] * B^0 (mod MOD)
65+
```
66+
67+
→ ローリングで更新:
68+
69+
```
70+
H_new = (H_old - s[i] * B^(k-1)) * B + s[i+k]
71+
```
72+
73+
### ⛓️ ローリングの流れ
74+
75+
```text
76+
例: s = "NANANANANA", k = 3, BASE = 1000003
77+
78+
部分列 ハッシュ計算 ハッシュ値登録
79+
-------- ----------------------------- --------------
80+
"NAN" → ord('N') * B^2 + ord('A') * B + ord('N') → H1 → seen = {H1}
81+
"ANA" → ローリングで計算 → H2 → seen = {H1, H2}
82+
"NAN" → H3 = H1(衝突発生) → 重複検出!True
83+
```
84+
85+
---
86+
87+
## 🔍 詳細解析③:**`find_max_duplicate_length()` の処理**
88+
89+
この関数は **二分探索で `k` の最大値**を探しています。
90+
91+
### 🔍 探索の流れ
92+
93+
```text
94+
N = 10
95+
範囲:k ∈ [0, N-1] = [0, 9]
96+
97+
初期:
98+
left = 0
99+
right = 9
100+
result = 0
101+
102+
step1: mid = (0+9)//2 = 4 → 長さ4の重複があるか?
103+
→ YES → result = 4, left = 5
104+
105+
step2: mid = (5+9)//2 = 7 → YES → result = 7, left = 8
106+
107+
step3: mid = (8+9)//2 = 8 → YES → result = 8, left = 9
108+
109+
step4: mid = 9 → NO → right = 8
110+
111+
終了: left > right → 最大長 = result = 8
112+
```
113+
114+
---
115+
116+
## 💡 出力例での解析: `"NANANANANA"` のとき
117+
118+
### 🔠 文字列の構造
119+
120+
```
121+
S = N A N A N A N A N A
122+
↑ ↑ ↑
123+
"NAN" が繰り返し出現
124+
```
125+
126+
* 長さ 3 の "NAN"
127+
* 長さ 4 の "NANA"
128+
* 長さ 6 の "NANANA"
129+
* 長さ 8 の "NANANANA"
130+
131+
→ 最長の重複 = 長さ **8**
132+
133+
---
134+
135+
## 💾 処理時間・メモリの見積り
136+
137+
| 処理 | 計算量 | 備考 |
138+
| --------- | ------------ | ----------------------- |
139+
| 二分探索 | `O(log N)` | 最大で \~16回探索 (N ≤ 50000) |
140+
| 各kのハッシュ計算 | `O(N)` | ローリングで高速更新 |
141+
| 合計 | `O(N log N)` | 実用十分高速 |
142+
| メモリ | `O(N)` | ハッシュ値をセットに保持 |
143+
144+
---
145+
146+
## ✅ 結論まとめ
147+
148+
| 要素 | 内容 |
149+
| ---------- | ------------------- |
150+
| アルゴリズム | ローリングハッシュ + 二分探索 |
151+
| 処理時間 | `O(N log N)`(高速) |
152+
| メモリ使用量 | `O(N)`(効率的) |
153+
| Pythonでの工夫 | 定数定義、高速I/O、MOD計算の工夫 |
154+
155+
---

Algorithm/Rolling Hash/other/same substring/same-substring.js

Whitespace-only changes.

0 commit comments

Comments
 (0)