티스토리 뷰
문제
https://www.acmicpc.net/problem/1893
알고리즘
KMP
풀이
문제 이해가 조금 어려운(?) 문제였습니다. S 에서 W 를 찾되, W를 A에 따라 시프트 하며 새로운 W′에 대해서도 KMP를 수행하는 문제입니다. KMP를 수행하는 방식은 어렵지 않으니 남은 과제는 W를 어떻게 움직여야 하나 고민해야 합니다. 시프트를 수행할 때, 우리가 알아야할 정보는 현재 문자의 다음 문자를 알면 되므로 conv 배열을 통하여 해결하도록 합시다. KMP를 A 만큼 수행하고 새로운 W′를 만드는 데는 W 길이 만큼이 소요되므로 시간 복잡도는 O(A(W+S))입니다.
코드
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define REP(i,n) for(int i=1;i<=n;++i)
#define FAST cin.tie(NULL);cout.tie(NULL); ios::sync_with_stdio(false)
using namespace std;
int tc;
string A, W, S;
int main() {
FAST;
cin >> tc;
while (tc--) {
vector<int> ans;
cin >> A >> W >> S;
//다음 문자의 정보를 가지고 있는 map
map<char, char> conv;
int a = A.size();
for (int i = 0;i < a;++i)
conv[A[i]] = A[(i + 1)%a];
int w = W.size();
//A이하의 길이 만큼 shift를 수행한 결과를 업데이트 해주므로
//실제로 shift를 수행하는 길이는 0또는 1이다.
//ex)BCA는 ABC에서 1번 SHIFT 한결과, CAB는 ABC에서 2번 SHIFT한 결과
//지만 BCA 기준으로는 1번만 SHIFT 하면 된다.
for(int shift=0;shift<a;++shift){
if (shift != 0) {
for (int k = 0;k < w;++k)
W[k] = conv[W[k]];
}
int fail[50001]{};
//새로운 W의 실패함수
for (int i = 1, j = 0;i < w;++i) {
while (j && W[i] != W[j]) j = fail[j - 1];
if (W[i] == W[j]) fail[i] = ++j;
}
bool FIND = false;
int s = S.size();
//S에서 W를 찾는 kmp 알고리즘
for (int i = 0, j = 0;i < s;++i) {
while (j && S[i] != W[j]) j = fail[j - 1];
if (S[i] == W[j]) {
if (j ==w - 1) {
//아직 못찾았다면 true
if (!FIND) {
FIND = true;
j = fail[j];
}
//이미 찾았는데 또 발견했다면 false
else {
FIND = false;
break;
}
}
else ++j;
}
}
// 한개만 찾았다면 정답에 넣어주자
if (FIND)
ans.emplace_back(shift);
}
if (ans.size() == 0) {
cout << "no solution" << '\n';
}
else if (ans.size() == 1) {
cout << "unique: " << ans[0] << '\n';
}
else {
cout << "ambiguous: ";
for (auto x : ans)
cout << x << ' ';
cout << '\n';
}
}
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준 16229] 반복 패턴 (2) | 2020.07.08 |
---|---|
[백준 2401] 최대 문자열 붙여넣기 (0) | 2020.07.07 |
[백준 4354] 문자열 제곱 (0) | 2020.07.06 |
[백준 1701] Cubeditor (0) | 2020.07.05 |
[백준 1786] 찾기 (0) | 2020.07.05 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- sorting
- 스위핑
- SCC
- 정렬
- kmp
- dijkstra
- greedy
- Segment tree
- 세그먼트트리
- sweeping
- 이분탐색
- Suffix Array
- 이분매칭
- 동적계획법
- 펜윅트리
- 2-SAT
- knapsack
- spring
- implementation
- 좌표압축
- spring boot
- union find
- dfs
- 트라이
- bfs
- Oracle
- Fenwick
- string
- DP
- hld
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함