백준 16500번 문자열 판별
문제
알파벳 소문자로 이루어진 문자열 S와 단어 목록 A가 주어졌을 때, S를 A에 포함된 문자열을 한 개 이상 공백없이 붙여서 만들 수 있는지 없는지 구하는 프로그램을 작성하시오. A에 포함된 단어를 여러 번 사용할 수 있다.
문제풀이
사용한 알고리즘 : DP
(1) 코드 6
a~z 26개의 단어 중 어떤 것으로 끝나는지 구분하여 저장합니다.
'S[x] : 'x로 끝나는 단어' 라고 설정한 벡터를 하나 만들었습니다.
(2) 코드 7
'dp[k] : k~끝까지 만들 수 있는지 여부'라고 설정한 dp를 bool 형식으로 만들어줍니다.
우리 목표는 문자열 S 의 뒤에서부터 주어진 목록 A의 단어들을 채워 나가는 것입니다.
문자열 S의 첫번째 단어까지 채워지면 1을 출력할 것이고, 아니면 0을 출력할것입니다.
(3) 코드 20~40
문자열 S의 맨 뒤 글자부터 탐색을 할 것입니다.
i번째를 탐색할 시, i+1 까지 채워졌다면 i번째에 들어갈 수 있는 단어를 넣어볼 것입니다.
따라서 문자열 S 길이 바로 뒷 글자는 채워졌다고 생각하고 탐색을 시작합니다.
i번째 탐색시, S의 i번째와 같은 글자로 끝나는 단어들을 봅니다.
각 단어가 들어갈 수 있는지 확인하고,
들어갈 수 있다면 단어가 들어간 길이만큼 앞의 dp값을 최신화 해줍니다.
(4) 코드 42~43
dp[0]=true 이면 0에서~끝까지 채워질 수 있다는 것입니다.
이를 생각하여 답을 출력해줍니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
string S; | |
int N; | |
vector<string> arr[26]; // S[t] : 글자 t 로 끝나는 단어들 | |
bool dp[111]; // dp[x] : x ~ 끝까지 채울 수 있는지 여부 | |
int main() {ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> S; | |
cin >> N; | |
for (int i = 0; i < N; ++i) { // N 개의 단어들 | |
string ss; | |
cin >> ss; | |
int x = ss.back() - 'a'; // 끝 글자 | |
arr[x].push_back(ss); // 해당 단어로 끝난다고 생각해서 저장 | |
} | |
dp[S.length()] = true; // 바로 뒷 글자는 채워졌다고 생각 | |
for (int i = S.length() - 1; i >= 0; i--) { | |
if (!dp[i + 1]) continue; // 이전까지 채워졌는지 여부 확인 | |
int now = S[i] - 'a'; // S 의 현재 보고 있는 글자 | |
for (auto it : arr[now]) {// S[i] 와 같은 단어로 끝나는 애들만 탐색 | |
int L = it.length(); // 들어갈 단어길이 | |
int To = i - L + 1; // i 부터 L 길이의 단어를 앞으로 붙일 수 있는지 | |
if (To < 0) continue; // 단어길이가 넘어가면 pass | |
bool ok = true; | |
for (int j = 0; j < L; ++j) { | |
if (S[i - j] != it[(L - 1) - j]) { | |
ok = false; | |
break; | |
} | |
} | |
if (ok) dp[To] = true; // dp값 최 | |
} | |
} | |
if (dp[0]) cout << 1 << '\n'; | |
else cout << 0 << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!