Skip to content

Commit 60a2bff

Browse files
authored
Merge pull request #59 from myoshi2891/dev/macbook_pro
Dev/macbook pro
2 parents f4dacbd + 50ef142 commit 60a2bff

10 files changed

Lines changed: 973 additions & 6 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
function longestPalindrome(s: string): string {
2+
if (s.length <= 1) return s;
3+
4+
let start = 0;
5+
let end = 0;
6+
7+
const expandAroundCenter = (left: number, right: number): void => {
8+
while (left >= 0 && right < s.length && s[left] === s[right]) {
9+
left--;
10+
right++;
11+
}
12+
// [left+1, right-1] が現在の回文
13+
if (right - left - 1 > end - start) {
14+
start = left + 1;
15+
end = right - 1;
16+
}
17+
};
18+
19+
for (let i = 0; i < s.length; i++) {
20+
expandAroundCenter(i, i); // 奇数長の回文中心
21+
expandAroundCenter(i, i + 1); // 偶数長の回文中心
22+
}
23+
24+
return s.slice(start, end + 1);
25+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function longestPalindromDP(s: string): string {
2+
const n = s.length;
3+
if (n < 2) return s;
4+
5+
// dp[i][j] = s[i..j] が回文かどうか
6+
const dp: boolean[][] = Array.from({ length: n }, () => Array(n).fill(false));
7+
8+
let start = 0;
9+
let maxLen = 1;
10+
11+
// 1文字は必ず回文
12+
for (let i = 0; i < n; i++) {
13+
dp[i][i] = true;
14+
}
15+
16+
// 長さ2以上の部分文字列を検討
17+
for (let len = 2; len <= n; len++) {
18+
for (let i = 0; i <= n - len; i++) {
19+
const j = i + len - 1;
20+
21+
if (s[i] === s[j]) {
22+
if (len === 2) {
23+
dp[i][j] = true;
24+
} else {
25+
dp[i][j] = dp[i + 1][j - 1];
26+
}
27+
28+
if (dp[i][j] && len > maxLen) {
29+
start = i;
30+
maxLen = len;
31+
}
32+
}
33+
}
34+
}
35+
36+
return s.substring(start, start + maxLen);
37+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
以下は、**TypeScript** を使って「最長回文部分文字列」を求める解法です。中心展開法(expand around center)を使って、**O(N²)** の時間計算量で実装できます。
2+
3+
---
4+
5+
### ✅ コード(TypeScript)
6+
7+
```ts
8+
function longestPalindrome(s: string): string {
9+
if (s.length <= 1) return s;
10+
11+
let start = 0;
12+
let end = 0;
13+
14+
const expandAroundCenter = (left: number, right: number): void => {
15+
while (left >= 0 && right < s.length && s[left] === s[right]) {
16+
left--;
17+
right++;
18+
}
19+
// [left+1, right-1] が現在の回文
20+
if (right - left - 1 > end - start) {
21+
start = left + 1;
22+
end = right - 1;
23+
}
24+
};
25+
26+
for (let i = 0; i < s.length; i++) {
27+
expandAroundCenter(i, i); // 奇数長の回文中心
28+
expandAroundCenter(i, i + 1); // 偶数長の回文中心
29+
}
30+
31+
return s.slice(start, end + 1);
32+
}
33+
```
34+
35+
---
36+
37+
### 🔍 解説
38+
39+
#### 🔸中心展開法とは?
40+
41+
文字列の各インデックス `i` を中心として、左右に文字が対称かどうかを確認して最長の回文を探す方法です。回文には以下の2パターンがあります:
42+
43+
* 奇数長(例: `"aba"`) → 中心は1文字
44+
* 偶数長(例: `"abba"`)→ 中心は2文字
45+
46+
#### 🔸処理フロー図(例: `"babad"`
47+
48+
```
49+
i = 0: 中心 = "b" → "bab" が回文
50+
i = 1: 中心 = "a" → "aba" が回文
51+
i = 2: 中心 = "b" → "bab" が回文
52+
i = 3: 中心 = "a" → "a"
53+
...
54+
最長は "bab" または "aba"
55+
```
56+
57+
---
58+
59+
### 🧪 テスト
60+
61+
```ts
62+
console.log(longestPalindrome("babad")); // "bab" or "aba"
63+
console.log(longestPalindrome("cbbd")); // "bb"
64+
console.log(longestPalindrome("a")); // "a"
65+
console.log(longestPalindrome("ac")); // "a" or "c"
66+
```
67+
68+
---
69+
70+
### ⏱️ 計算量
71+
72+
* 時間計算量:O(N²)
73+
* 空間計算量:O(1)
74+
75+
---
76+
77+
**動的計画法(DP)を用いた TypeScript 実装**
78+
この方法は、部分文字列 `s[i..j]` が回文かどうかを記録し、そこから最長の回文部分文字列を探索します。
79+
80+
---
81+
82+
## ✅ TypeScript 実装(動的計画法)
83+
84+
```ts
85+
function longestPalindrome(s: string): string {
86+
const n = s.length;
87+
if (n < 2) return s;
88+
89+
// dp[i][j] = s[i..j] が回文かどうか
90+
const dp: boolean[][] = Array.from({ length: n }, () => Array(n).fill(false));
91+
92+
let start = 0;
93+
let maxLen = 1;
94+
95+
// 1文字は必ず回文
96+
for (let i = 0; i < n; i++) {
97+
dp[i][i] = true;
98+
}
99+
100+
// 長さ2以上の部分文字列を検討
101+
for (let len = 2; len <= n; len++) {
102+
for (let i = 0; i <= n - len; i++) {
103+
const j = i + len - 1;
104+
105+
if (s[i] === s[j]) {
106+
if (len === 2) {
107+
dp[i][j] = true;
108+
} else {
109+
dp[i][j] = dp[i + 1][j - 1];
110+
}
111+
112+
if (dp[i][j] && len > maxLen) {
113+
start = i;
114+
maxLen = len;
115+
}
116+
}
117+
}
118+
}
119+
120+
return s.substring(start, start + maxLen);
121+
}
122+
```
123+
124+
---
125+
126+
## 🔍 処理概要
127+
128+
### 🧠 dp\[i]\[j] の定義:
129+
130+
* `dp[i][j] = true` なら `s[i..j]` が回文
131+
132+
### 🔄 状態遷移:
133+
134+
* `s[i] !== s[j]``dp[i][j] = false`
135+
* `s[i] === s[j]`
136+
137+
* 長さ2 → `dp[i][j] = true`
138+
* 長さ3以上 → `dp[i][j] = dp[i+1][j-1]`
139+
140+
---
141+
142+
## 🧪 例: `"babad"` の場合
143+
144+
```
145+
i=0, j=2 -> "bab" => dp[0][2] = dp[1][1] = true → 回文
146+
i=1, j=3 -> "aba" => dp[1][3] = dp[2][2] = true → 回文
147+
最長は "bab" または "aba"
148+
```
149+
150+
---
151+
152+
## ⏱️ 計算量
153+
154+
* 時間計算量:`O(N²)`
155+
* 空間計算量:`O(N²)`(2次元配列)
156+
157+
---
158+
159+
## ✅ テスト例
160+
161+
```ts
162+
console.log(longestPalindrome("babad")); // "bab" または "aba"
163+
console.log(longestPalindrome("cbbd")); // "bb"
164+
console.log(longestPalindrome("a")); // "a"
165+
console.log(longestPalindrome("ac")); // "a" または "c"
166+
```
167+
168+
---

DataStructures/Trees/BinaryIndexedTree/FenwickTree/atcoder/A59/A59.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,33 @@
22
input = sys.stdin.read
33

44
class FenwickTree:
5-
def __init__(self, size):
5+
def __init__(self, size: int):
66
self.n = size
77
self.tree = [0] * (size + 1) # 1-indexed
88

9-
def add(self, index, value):
9+
def add(self, index: int, value: int):
1010
while index <= self.n:
1111
self.tree[index] += value
1212
index += index & -index
1313

14-
def sum(self, index):
14+
def sum(self, index: int) -> int:
1515
result = 0
1616
while index > 0:
1717
result += self.tree[index]
1818
index -= index & -index
1919
return result
2020

21-
def range_sum(self, left, right):
21+
def range_sum(self, left: int, right: int) -> int:
2222
return self.sum(right - 1) - self.sum(left - 1)
2323

2424
def main():
2525
data = input().split()
2626
N = int(data[0])
27-
Q = int(data[1])
2827

2928
bit = FenwickTree(N)
3029
A = [0] * (N + 1) # 1-indexed
3130

32-
res = []
31+
res: list[str] = [] # Type hint for the list of strings
3332
idx = 2
3433
while idx < len(data):
3534
if data[idx] == '1':
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strconv"
8+
)
9+
10+
type FenwickTree struct {
11+
n int
12+
data []int
13+
}
14+
15+
func NewFenwickTree(n int) *FenwickTree {
16+
return &FenwickTree{
17+
n: n + 2,
18+
data: make([]int, n+3),
19+
}
20+
}
21+
22+
func (ft *FenwickTree) Update(i int) {
23+
i++
24+
for i < ft.n {
25+
ft.data[i]++
26+
i += i & -i
27+
}
28+
}
29+
30+
func (ft *FenwickTree) Query(i int) int {
31+
i++
32+
res := 0
33+
for i > 0 {
34+
res += ft.data[i]
35+
i -= i & -i
36+
}
37+
return res
38+
}
39+
40+
func CountInversions(arr []int, N int) int {
41+
ft := NewFenwickTree(N)
42+
inv := 0
43+
for i := len(arr) - 1; i >= 0; i-- {
44+
inv += ft.Query(arr[i] - 1)
45+
ft.Update(arr[i])
46+
}
47+
return inv
48+
}
49+
50+
func main() {
51+
scanner := bufio.NewScanner(os.Stdin)
52+
scanner.Split(bufio.ScanWords)
53+
54+
nextInt := func() int {
55+
scanner.Scan()
56+
v, _ := strconv.Atoi(scanner.Text())
57+
return v
58+
}
59+
60+
N := nextInt()
61+
grid := make([][]int, N)
62+
for i := 0; i < N; i++ {
63+
grid[i] = make([]int, N)
64+
for j := 0; j < N; j++ {
65+
grid[i][j] = nextInt()
66+
}
67+
}
68+
69+
rowPos := make([]int, N+1)
70+
colPos := make([]int, N+1)
71+
72+
// 位置記録
73+
for i := 0; i < N; i++ {
74+
for j := 0; j < N; j++ {
75+
val := grid[i][j]
76+
if val != 0 {
77+
rowPos[val] = i
78+
colPos[val] = j
79+
}
80+
}
81+
}
82+
83+
rowPerm := make([]int, N)
84+
colPerm := make([]int, N)
85+
for k := 1; k <= N; k++ {
86+
rowPerm[k-1] = rowPos[k]
87+
colPerm[k-1] = colPos[k]
88+
}
89+
90+
rowMoves := CountInversions(rowPerm, N)
91+
colMoves := CountInversions(colPerm, N)
92+
93+
fmt.Println(rowMoves + colMoves)
94+
}

0 commit comments

Comments
 (0)