https://www.acmicpc.net/problem/2941
예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.
크로아티아 알파벳 변경
č c=
ć c-
dž dz=
đ d-
lj lj
nj nj
š s=
ž z=
예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.
dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.
처음 읽었을 땐 이해가 잘 안 되었다.
모든 문자에 ~가 붙으면 =으로 치환하고, ` 가 붙으면 -로 치환하는 방식으로 생각했다.
하지만 위 목록에 없는 알파벳은 한 글자씩 센다고 써있다.
따라서 일단 저 위 8개의 알파벳만 조사하는 방식으로 구현했다.
포함되는 지 안 되는지 조사할때 내가 자주 애용하는 방식으로 Set을 사용하였다.
Set에 8글자를 넣고, 입력 문자열의 매 알파벳마다 set에 포함되는지 조사했다.
크로아티아 알파벳이 최대 세글자이다.
따라서 입력문자열의 각 char형 원소 조사할 때, 그 뒤 두개의 원소까지 탐색했다.
//입력으로 들어온 문장 길이만큼 반복
for(int i=0;i<input.size();i++){
int cur=i;
string elem="";
bool foundInSet=false;
//크로아티아 알파벳이 최대 3글자이므로 현재 인덱스에서 3개만큼 봄
for(cur;cur<i+3;cur++){
//범위 넘어가면 인덱스오류나므로
if(cur>=input.size()) break;
elem += input[cur];
//겹치는 문자가 (ex) d-, d--) 없으므로 찾으면 바로 종료
if(s.find(elem)!=s.end()){
numAlphabet++;
foundInSet=true;
break;
}
}
if(!foundInSet)
numAlphabet++;
else
i=cur;
}
만약 "lj"처럼 두 개가 일치하여 알파벳으로 셌을 때는
인덱스를 해당 알파벳 갯수만큼 넘겨야한다. ("lj"일때는 2개만큼 넘기기)
따라서 foundInSet이 true일땐 i값을 cur로 변경해서 반복문을 실행했다.
#include<iostream>
#include<set>
using namespace std;
int main(){
set<string> s;
s.insert("c=");
s.insert("c-");
s.insert("dz=");
s.insert("d-");
s.insert("lj");
s.insert("nj");
s.insert("s=");
s.insert("z=");
string input;
cin>>input;
int numAlphabet=0;
//입력으로 들어온 문장 길이만큼 반복
for(int i=0;i<input.size();i++){
int cur=i;
string elem="";
bool foundInSet=false;
//크로아티아 알파벳이 최대 3글자이므로 현재 인덱스에서 3개만큼 봄
for(cur;cur<i+3;cur++){
//범위 넘어가면 인덱스오류나므로
if(cur>=input.size()) break;
elem += input[cur];
//겹치는 문자가 (ex) d-, d--) 없으므로 찾으면 바로 종료
if(s.find(elem)!=s.end()){
numAlphabet++;
foundInSet=true;
break;
}
}
if(!foundInSet)
numAlphabet++;
else
i=cur;
}
cout<<numAlphabet;
}