문제 링크: https://www.acmicpc.net/problem/3107

 

축약된 IPv6 주소를 복원하는 문제입니다.

콜론 두개(::)가 있는지 찾고, 있으면 압축된걸 풀어줍니다. 푸는 방법은 콜론 두개로 압축되지 않은 그룹의 개수를 세고 8-그룹수 만큼 :0000:0000...:0000:을 만들어 주면 됩니다. 이때 콜론 두개의 인덱스를 확인해서 맨 앞에 있으면 맨 앞의 ":"가 들어가면 안되고, 맨 뒤에 있으면 맨 뒤의 ":"가 들어가면 안됩니다.

:: 위치에 위에 만들어놓은 :0000~~를 껴 넣습니다. string의 replace 메서드를 쓰면 간편합니다

 

그 다음, ipv6 string을 콜론을 delimiter로 분리해서 0이 생략된 부분에 0을 붙인 다음 다시 합칩니다

c++은 split 함수가 딱히 없기 때문에 stringstream을 쓰거나 여타 방법으로 잘 구현해야 합니다.

 

#pragma GCC optimize ("Ofast")

#define _CRT_SECURE_NO_WARNINGS
#define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING
#include <bits/stdc++.h>
using namespace std;


int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif

	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

	string ipv6;
	cin >> ipv6;

	int groups = 0;
	for (int i = 0; i < ipv6.size();) {
		if (ipv6[i] != ':') {
			++groups;
			while (i < ipv6.size() && ipv6[i] != ':')
				++i;
		}
		else {
			++i;
		}
	}

	auto double_colon = ipv6.find("::", 0, 2);
	if (double_colon != string::npos) {
		string snippet;

		// 만들기
		if (double_colon != 0) {
			snippet = ':';
		}
		for (int i = 0; i < 8-groups; ++i) {
			snippet += "0000";
			if (i+1 != 8-groups)
				snippet += ':';
		}

		if (double_colon != ipv6.size()-2) {
			snippet += ':';
		}

		ipv6.replace(double_colon, 2, snippet);
	}


	// zero-fill
	string out;
	bool first = true;
	istringstream iss(ipv6);
	string token;
	while (getline(iss, token, ':')) {
		if (token.size() != 4)
			token = string(4 - token.size(), '0') + token;
	
		if (first)
			first = false;
		else
			out += ":";

		out += token;
	}
	cout << out << '\n';

	return 0;
}
반응형