题目描述
IPv6格式
IPv6二进位制下为128位长度,以16位为一组,每组以冒号“:”隔开,可以分为8组,每组以4位十六进制方式表示。
例如:2001:0db8:0000:0000:0123:4567:89ab:cdef 是一个合法的IPv6地址。
同时IPv6地址在某些条件下可以压缩:
每组数字代表的独立16进制数可以省略前位的0。
例如上面的IPv6地址可被压缩为:
2001:db8:0:0:123:4567:89ab:cdef
可以用双冒号“::”表示一组0或多组连续的0,但只能出现一次
例如上面的IPv6地址可被压缩为:
2001:db8::123:4567:89ab:cdef
请你帮助记忆力不好的网络工程师小明解决他遇到的问题。
规则补充:
输入数据为完全展开的IPv6地址,确保输入的IPv6地址不含双冒号,每组地址省略的0都会被补充上去。
双冒号只能使用一次,因此我们压缩最长的全0组
比如:2001:0db8:0000:0000:1:0000:0000:0000
我们压缩为2001:db8:0:0:1::,而非2001:db8::1:0:0:0
双冒号只能只用一次,因此我们在我们遇到地址中多个连续全0组长度相同时,我们压缩最前面的一个。
2001:0db8:0000:0000:ffff:0000:0000:1
压缩为2001:db8::ffff:0:0:1,而非2001:db8:0:0:ffff::1
输入的IPv6地址可能无法被压缩,因此请照原样输出。
提示:本题所示的压缩规则与macOS(Darwin)默认的IPv6地址显示方式相同,而Windows和Linux只遇到一组全0时不会使用::进行压缩。但用此方法压缩过的IPv6地址一样可以被Windows和Linux正确识别。
例如:2001:0db8:ffff:0000:0123:4567:89ab:cdef
Darwin压缩为:2001:db8:ffff::123:4567:89ab:cdef
Linux、Windows压缩为:2001:db8:ffff:0:123:4567:89ab:cdef
输入格式
一串39个字符的字符串,代表一个完全展开的IPv6地址
输出格式
一串压缩后的IPv6地址
输入输出样例
输入:240e:0014:6000:0000:0000:0000:0000:0001
输出:240e:14:6000::1
AC代码
#include <bits/stdc++.h>
using namespace std;
string addr_full;
string sections[8];
int section_isZero[8] = {};
struct ommit_section {
int len, start, end;
};
/* 0 start */
string get_section(int i) {
int start;
start = i * 5;
return addr_full.substr(start, 4);
}
string edit_section(int i) {
section_isZero[i] = (sections[i][0] == '0' && sections[i][1] == '0' &&
sections[i][2] == '0' && sections[i][3] == '0');
if (section_isZero[i]) {
sections[i] = "0";
return sections[i];
}
//先看这段是不是全0
string tmp;
int flag = 0;
for (int j = 0; j <= 3; j++) {
if (sections[i][j] != '0') {
flag = j;
break;
}
}
tmp = sections[i].substr(flag, 4 - flag);
sections[i] = tmp;
return tmp;
}
int main() {
cin >> addr_full;
/* 一个IPV6地址最多分8段 */
for (int i = 0; i < 8; i++) {
sections[i] = get_section(i);
edit_section(i);
}
vector<struct ommit_section> os;
for (int i = 0; i < 8; i++) {
if (section_isZero[i] == 1) {
int cnt = 1, start = i, end;
for (int j = i + 1; j <= 8; j++) {
if (section_isZero[j] == 0 || j == 8) {
end = j - 1;
struct ommit_section tmp = {cnt, start, end};
os.push_back(tmp);
i = j;
break;
} else
cnt++;
}
}
}
int max_len = 0, start = -1, end = 8;
for (int i = 0; i < os.size(); i++) {
if (max_len < os[i].len) {
max_len = os[i].len;
start = os[i].start;
end = os[i].end;
}
}
if (start >= 0 && end <= 7) {
for (int i = 0; i < start; i++) {
cout << sections[i] << ":";
}
if (start == 0)
cout << ":";
cout << ":";
for (int i = end + 1; i < 8; i++) {
cout << sections[i];
if (i != 7)
cout << ":";
}
} else {
for (int i = 0; i < 7; i++) {
cout << sections[i] << ":";
}
cout << sections[7];
}
}
没有算法,暴力模拟就完事了