Skip to content

Commit cd0de0a

Browse files
authored
feat: menambahkan algoritma boyer moore (#111)
* feat: menambahkan algoritma boyer moore Signed-off-by: slowy07 <[email protected]> * fix: memperbaiki over read kode informasi kode issue: Nama: CWE-126 Informasi: https://cwe.mitre.org/data/definitions/126.html Signed-off-by: slowy07 <[email protected]> --------- Signed-off-by: slowy07 <[email protected]>
1 parent 8a618cc commit cd0de0a

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed

strings/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
file(GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
2+
foreach(testsourcefile ${APP_SOURCES})
3+
string(REPLACE ".cpp" testname ${testsourcefile})
4+
add_executable(${testname} ${testsourcefile})
5+
set_target_properties(${testname} PROPERTIES LINKER_LANGUAGE CXX)
6+
if(OpenMP_CXX_FOUND)
7+
target_link_libraries(${testname} OpenMP::OpenMP_CXX)
8+
endif()
9+
install(TARGETS ${testname} DESTINATIN "bin/strings")
10+
endforeach(testsourcefile ${APP_SOURCES})

strings/boyer_moore.cpp

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
#include <cassert>
2+
#include <cstddef>
3+
#include <cstring>
4+
#include <iostream>
5+
#include <ostream>
6+
#include <string>
7+
#include <vector>
8+
#define UKURAN_ALFABET
9+
10+
/**
11+
* @namespace
12+
* @brief Algoritma string
13+
*/
14+
namespace strings {
15+
/**
16+
* @namespace
17+
* @brief fungsi untuk implementasi algoritma booyer-moore
18+
*/
19+
namespace boyer_moore {
20+
struct pola {
21+
// pola yang akan dicari
22+
std::string pola_teks;
23+
// tabel karaketer yang buruk yang digunakan heuristik karakter
24+
// buruk pada algoritma
25+
std::vector<size_t> karakter_buruk;
26+
// tabel awalan baik yang digunakan dalama heuristik awalan baik
27+
// pada algoritma boyer moore
28+
std::vector<size_t> awalan_baik;
29+
};
30+
31+
/**
32+
* @brief fungsi untuk memproses tabel awaln baik
33+
*
34+
* @param teks string yang akan diproses
35+
* @param arg tabel awalan baik yang akan diisi
36+
* @return void
37+
*/
38+
void inisialisasi_awalan_baik(const std::string &teks,
39+
std::vector<size_t> &arg) {
40+
// resize tabel awalan baik sesuasi ukuran string
41+
arg.resize(teks.size() + 1, 0);
42+
43+
std::vector<size_t> posisi_perbatasan(teks.size() + 1, 0);
44+
// inisialisasi karakter saat ini dengan panjang string
45+
size_t karaketer_saat_ini = teks.length();
46+
// inisialisasi indeks perbatasan
47+
size_t indeks_perbatasan = teks.length() + 1;
48+
// set perbatasan terakhir
49+
posisi_perbatasan[karaketer_saat_ini] = indeks_perbatasan;
50+
51+
// prosesa perbatasan untuk menemukan awalan baik
52+
while (karaketer_saat_ini > 0) {
53+
while (indeks_perbatasan <= teks.length() &&
54+
teks[karaketer_saat_ini - 1] != teks[indeks_perbatasan - 1]) {
55+
if (arg[indeks_perbatasan] == 0) {
56+
arg[indeks_perbatasan] = indeks_perbatasan - karaketer_saat_ini;
57+
}
58+
indeks_perbatasan = posisi_perbatasan[indeks_perbatasan];
59+
}
60+
61+
// kurangi karaketer yang sedang diperiksa
62+
karaketer_saat_ini--;
63+
indeks_perbatasan--;
64+
posisi_perbatasan[karaketer_saat_ini] = indeks_perbatasan;
65+
}
66+
67+
// mementukan perbatasan terbesar
68+
size_t indeks_perbatasan_terbesar = posisi_perbatasan[0];
69+
70+
// isi tabel awalan baik untuk seluruh karakter
71+
for (size_t i = 0; i < teks.size(); i++) {
72+
if (arg[i] == 0) {
73+
// set nilai ke perbatasan
74+
arg[i] = indeks_perbatasan_terbesar;
75+
}
76+
// jika melewati perbatasan terbesar, cari perbatasan selanjutnya
77+
if (i == indeks_perbatasan_terbesar) {
78+
indeks_perbatasan_terbesar =
79+
posisi_perbatasan[indeks_perbatasan_terbesar];
80+
}
81+
}
82+
}
83+
84+
/**
85+
* @brief fungsi untuk memproses tabel karakter buruk
86+
*
87+
* @param teks string yang akan diproses
88+
* @param arg tabel karakter buruk yang akan diisi
89+
* @return void
90+
*/
91+
void inisialisasi_karakter_buruk(const std::string &teks,
92+
std::vector<size_t> &arg) {
93+
arg.resize(teks.length());
94+
95+
// isi table karakter buruk dengan jarak pergeseran berdasarkan karakter
96+
for (size_t i = 0; i < teks.length(); i++) {
97+
// hitung jarak pergeseran untuk karakter tertentu
98+
arg[teks[i]] = teks.length() - i - 1;
99+
}
100+
}
101+
102+
/**
103+
* @brief fungsi untuk menginisialisasi pola
104+
*
105+
* @param teks yang digunakan untuk inisialisasi
106+
* @param arg struktur pola yang diinisialisasi
107+
* @return void
108+
*/
109+
void inisialisasi_pola(const std::string &teks, pola &arg) {
110+
arg.pola_teks = teks;
111+
inisialisasi_karakter_buruk(teks, arg.karakter_buruk);
112+
inisialisasi_awalan_baik(teks, arg.awalan_baik);
113+
}
114+
115+
/**
116+
* @brief fungsi implementasi algoritma boyer moore
117+
*
118+
* @param teks teks yang akan dicari data pola
119+
* @param arg struktur pola yang mengandung pola yang sudah di proses
120+
* @return vektor indeks yang menyimpan kemunculan pola dalam teks
121+
*/
122+
std::vector<size_t> cari(const std::string &teks, const pola &arg) {
123+
// inisialisasi posisi indeks pencarian
124+
size_t posisi_indeks = arg.pola_teks.size() - 1;
125+
// vektor untuk menyimpan hasil pencarian
126+
std::vector<size_t> penyimpanan_indeks;
127+
128+
// lakukan pencarian
129+
while (posisi_indeks < teks.length()) {
130+
size_t indeks_teks = posisi_indeks;
131+
int indeks_pola = static_cast<int>(arg.pola_teks.size()) - 1;
132+
133+
// badingkan pola dengan teks dari belakang
134+
while (indeks_pola >= 0 &&
135+
teks[indeks_teks] == arg.pola_teks[indeks_pola]) {
136+
--indeks_pola;
137+
--indeks_teks;
138+
}
139+
140+
// jika pola cocok, save result indeks
141+
if (indeks_pola < 0) {
142+
penyimpanan_indeks.push_back(posisi_indeks - arg.pola_teks.length() + 1);
143+
posisi_indeks += arg.awalan_baik[0];
144+
} else {
145+
posisi_indeks += std::max(arg.karakter_buruk[teks[indeks_teks]],
146+
arg.awalan_baik[indeks_pola + 1]);
147+
}
148+
}
149+
150+
// return hasil pencarian
151+
return penyimpanan_indeks;
152+
}
153+
154+
/**
155+
* @brief fungsi untuk memeriksa apakah pola adalah prefix dari string
156+
*
157+
* @param teks pointer ke beberapa bagia teks input
158+
* @param pola pola yang sedang dicari
159+
* @return `true` jika pola adalah prefiks dari teks
160+
* @return `false` jika pola bukan prefiks dari teks
161+
*/
162+
bool adalah_prefix(const char *teks, const char *pola, size_t panjang) {
163+
// iterasi melalui setiap karakter dari teks dan pola
164+
for (size_t i = 0; i < panjang; i++) {
165+
// jika mencapai akhir teks (karakter null) atau karakter tidak cocok
166+
if (teks[i] == '\0' || teks[i] != pola[i]) {
167+
// pola tidak cocok
168+
return false;
169+
}
170+
}
171+
172+
// bandingkan karakter satu per satu
173+
for (size_t i = 0; i < panjang; i++) {
174+
if (teks[i] != pola[i]) {
175+
// jika ada perbedaan, maka bukan prefik
176+
return false;
177+
}
178+
}
179+
180+
// jika semua karakter cocok, pola adalah prefik
181+
return true;
182+
}
183+
} // namespace boyer_moore
184+
} // namespace strings
185+
186+
/**
187+
* @brief test case untuk mencari kemunculan kata `and`
188+
* @param teks teks yang digunakan untuk pencarian kata `and`
189+
* @return void
190+
*/
191+
void uji_and(const char *teks) {
192+
strings::boyer_moore::pola ands;
193+
strings::boyer_moore::inisialisasi_pola("and", ands);
194+
std::vector<size_t> indeks = strings::boyer_moore::cari(teks, ands);
195+
196+
assert(indeks.size() == 2);
197+
assert(strings::boyer_moore::adalah_prefix(teks + indeks[0], "and", 3));
198+
199+
std::cout << "Kata 'and' ditemukan pada indeks: ";
200+
for (size_t i : indeks) {
201+
std::cout << i << " ";
202+
}
203+
std::cout << std::endl;
204+
}
205+
206+
/**
207+
* @brief fungsi utama untuk menjalankan test case
208+
* @returns int nilai pengembalian dari status program
209+
*/
210+
int main() {
211+
const char *teks_uji = "and here and there";
212+
uji_and(teks_uji);
213+
return 0;
214+
}

0 commit comments

Comments
 (0)