[BaekJoon] 14426번 - 접두사 찾기 [Java][C++]
[BaekJoon] 14426번 - 접두사 찾기 [Java][C++]
1. 문제 풀이
집합 $S$ 에 포함된 $N$ 개의 문자열이 주어지고 이후 $M$ 개의 검사해야 하는 문자열이 주어진다. 검사해야 하는 각 문자열은 해당 문자열이 집합 $S$ 에 포함된 문자열 중 하나의 접두사가 되는지 카운팅을 해줘야 한다.
간단하게는 집합 $S$ 에 포함되는 $N$ 개의 문자열에 대해 각 문자열의 모든 접두사를 포함한 집합을 만들고 검사해야 하는 문자열이 해당 집합에 포함되는지 판단하면 된다. 기존의 집합 $S$ 보다는 크기가 커진 집합이 되지만 접두사만 생성할 수 있으면 검사는 간단하게 할 수 있다.
접두사를 통해 검사한다는 점에서 트라이 자료구조도 활용할 수 있는데 집합 $S$ 에 포함되는 문자열들을 모두 삽입한 트라이를 만들고 이후 검사해야 하는 문자열이 해당 트라이에서 발견될 수 있는지 찾아도 된다.
2. 코드
1. Set/Map [Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
Set<String> set = new HashSet<>();
while (n-- > 0) {
String s = br.readLine();
for (int i = 0; i < s.length(); i++) {
set.add(s.substring(0, i + 1));
}
}
int cnt = 0;
while (m-- > 0) {
if (set.contains(br.readLine())) cnt++;
}
System.out.println(cnt);
}
}
2. Trie [Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.io.*;
import java.util.*;
public class Main {
static final int MX = 1 + 10000 * 500;
static final int ROOT = 0;
static int unused = ROOT + 1;
static int[][] nxt = new int[MX][26];
static void insert(String s) {
int cur = ROOT;
for (char c : s.toCharArray()) {
int idx = c - 'a';
if (nxt[cur][idx] == 0) nxt[cur][idx] = unused++;
cur = nxt[cur][idx];
}
}
static boolean find(String s) {
int cur = ROOT;
for (char c : s.toCharArray()) {
int idx = c - 'a';
if (nxt[cur][idx] == 0) return false;
cur = nxt[cur][idx];
}
return true;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
while (n-- > 0) {
insert(br.readLine());
}
int cnt = 0;
while (m-- > 0) {
if (find(br.readLine())) cnt++;
}
System.out.println(cnt);
}
}
3. Set/Map [C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
unordered_set<string> st;
while (n--) {
string s;
cin >> s;
for (int i = 0; i < s.size(); i++) {
st.insert(s.substr(0, i + 1));
}
}
int cnt = 0;
while (m--) {
string s;
cin >> s;
if (st.count(s)) cnt++;
}
cout << cnt;
}
4. Trie [C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>
using namespace std;
const int MX = 1 + 10000 * 500;
const int ROOT = 0;
int unused = ROOT + 1;
int nxt[MX][26];
void insert(string& s) {
int cur = ROOT;
for (char c : s) {
int idx = c - 'a';
if (nxt[cur][idx] == 0) nxt[cur][idx] = unused++;
cur = nxt[cur][idx];
}
}
bool find(string& s) {
int cur = ROOT;
for (char c : s) {
int idx = c - 'a';
if (nxt[cur][idx] == 0) return false;
cur = nxt[cur][idx];
}
return true;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
while (n--) {
string s;
cin >> s;
insert(s);
}
int cnt = 0;
while (m--) {
string s;
cin >> s;
if (find(s)) cnt++;
}
cout << cnt;
}
This post is licensed under CC BY 4.0 by the author.