긴 문자열에서 특정 단어를 찾을때 사용하는 알고리즘이다.
원래의 시간 복잡도는 특정단어 * 긴문자열 이라는 시간이 나오는데 이것을 줄인 것이다.
알고리즘 이해가 좀 어렵다. 모르면 꼭 다른곳을 찾아봐서 복습하자
string 은 char[100000] 으로 해서 풀어도 된다. 설마 여기까지 왔는데 이걸 변환 못하는건 말이 안되지 않을까?
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#include <iostream>
#include <string>
#define pii pair<int, int>
using namespace std;
int p_fail[1000000] = { 0 };
int ans[1000000];
int siz= 0;
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
string t, p;
getline(cin, t);
getline(cin, p);
/*
fail 함수를 구해보자.
p_fail 함수는 문자열 p의 처음 글자중 일치하는 접두사의 최대 길이이다.
그리고 p_fail[i] 는 일치하는 접두사들의 다음 문자이다.
abcabcabca 의 fail 함수는??? -> 0 0 0 1 2 3 4 5 6 7
abacabad 의 fail 함수는 ??? -> 0 0 1 0 1 2 3 0
while(base > 0 && p[i] != p[base]) 가 정말 제일 중요하다.
abacabad 에서 i가 7일때를 보자. (그러면 base는 3부터 시작한다.)
p[7] 와 p[3] 을 비교해서 다르니깐 base는 p_fail[3-1] => 1이다.
p[7] 와 p[1] 을 비교해서 다르니깐 base는 p_fail[1-1] -> 0 이다.
0 이면 break 고
p[i] == p[base]도 false니깐 0이된다.
*/
int base = 0;
for (int i = 1; i < p.size(); i++)
{
while (base > 0 && p[i] != p[base])
base = p_fail[base - 1];
if (p[i] == p[base])
p_fail[i] = ++base;
}
base = 0;
/*
abcabcabcabcabcabcabcabca
abcabca 를 기준으로 해보자. fail 함수는 0 0 0 1 2 3 4
while (base > 0 && t[i] != p[base]) 은 fail 함수와 비슷하고
i가 6인 상태에서 t[i] == p[base] 이고 base == 6 == p_size-1 이니깐
base = p_fail[base] 이다. p_fail[6] = 4 니깐
문자를 완전히 찾았을때 base값은 겹치는 문자열들의 다음값으로 잡아주는 것이다.
*/
for (int i = 0; i < t.size(); i++)
{
while (base > 0 && t[i] != p[base])
base = p_fail[base - 1];
if (t[i] == p[base])
{
if (base == p.size() - 1)
{
ans[siz++] = i - base + 1;
base = p_fail[base];
}
else
{
base++;
}
}
}
cout << siz << '\n';
for (int i = 0; i < siz; i++)
cout << ans[i] << ' ';
}
|
cs |
'알고리즘 기술' 카테고리의 다른 글
위상정렬 Feat DFS, BFS (0) | 2020.08.20 |
---|---|
Trie와 동적 Trie (0) | 2020.08.19 |
ccw (0) | 2020.07.16 |
최소 스패닝트리(MST) - 크루스칼 (0) | 2020.07.16 |
유니온 파인드 (0) | 2020.07.16 |