洛谷P2815 IPv6地址壓縮
題目描述
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]; } }
沒有演算法,暴力模擬就完事了