2019牛客暑期多校训练营(第六场)- Shorten IPv6 Address

模拟字符串处理

很暴力的方法,就是把能变成::的全部枚举一次,选最小的即可。。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define __fastIn ios::sync_with_stdio(false), cin.tie(0)
#define pb push_back
using namespace std;
typedef long long LL;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int ret = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        ret = (ret << 3) + (ret << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -ret : ret;
}
inline int lcm(int a, int b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
int _;
const string ch = "0123456789abcdef";
string s, t;

string calc(string &tmp){
    bool flag = true;
    string ret = "";
    for(int i = 0; i < 4; i ++){
        if(flag && tmp[i] == '0') continue;
        if(tmp[i] != '0') flag = false;
        ret.pb(tmp[i]);
    }
    if(ret.empty()) ret = "0";
    return ret;
}

string rebuild(string &str){
    int cnt = 0;
    string ret = "";
    for(auto &c: str){
        if(c == ':') cnt ++;
        else cnt = 0;
        if(cnt <= 2) ret.pb(c);
    }
    return ret;
}

bool cmp(const string &a, const string &b){
    if(a.size() != b.size()) return a.size() < b.size();
    return a < b;
}

int main(){

    //freopen("data.txt", "r", stdin);
    __fastIn;
    int cs = 0;
    for(cin >> _; _; _ --){
        cin >> s;
        t.clear();
        for(int i = 0; i < s.size(); i += 16){
            string str = s.substr(i, 16);
            string tmp = "";
            int st = 0;
            for(int j = 1; j <= 4; j ++){
                int val = 1, sum = 0;
                for(int k = st + 3; k >= st; k --){
                    sum += str[k] == '1' ? val : 0;
                    val <<= 1;
                }
                st += 4;
                tmp.pb(ch[sum]);
            }
            tmp = calc(tmp);
            t += tmp, t += ":";
        }
        vector<string> record, ans;
        string cur = "";
        for(int i = 0; i < t.size(); i ++){
            if(t[i] == ':'){
                record.pb(cur), cur.clear();
            }
            else cur += t[i];
        }
        for(int i = 0; i + 1 < record.size(); i ++){
            if(record[i] == record[i + 1] && record[i] == "0"){
                int k = 2;
                while(i + k < record.size() && record[i] == record[i + k]) k ++;
                k --;
                string str = "";
                for(int j = 0; j < record.size(); j ++){
                    if(j == i) str += "::", j += k;
                    else str += record[j];
                    str += ":";
                }
                str.pop_back();
                str = rebuild(str);
                ans.pb(str);
            }
        }
        cout << "Case #" << ++cs << ": ";
        if(ans.empty()){
            cout << record[0];
            for(int i = 1; i < record.size(); i ++){
                cout << ":" << record[i];
            }
            cout << endl;
        }
        else{
            cout << min_element(ans.begin(), ans.end(),
                                [](const string &a, const string &b){
                                    if(a.size() != b.size()) return a.size() < b.size();
                                    return a < b;
                                })->c_str() << endl;
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/onionQAQ/p/11296163.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值