洛谷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];
    }
}

没有算法,暴力模拟就完事了

posted @ 2020-09-06 19:05  Allegro_VivAce  阅读(515)  评论(0编辑  收藏  举报