一道有点坑点的题 题意 给定一个128位的01字符串 请简化这个字符串
128位 每4位代表一个16进制的数字 每16位代表4个16进制的数字 把128位的字符串转化为128/4=32位的16进制的字符串 其中每4个之间用:分割开 所以一共是32/4=8段 首先每段的前导0可以省略
其次 4个0可以化为0 可以把2个及2个以上的全0段 化简为:: 但是注意只能化简一次
输出最短的 多个相同输出字典序最小的
思路:
首先找出最长的0来 把最长的0段化简 前导0就不说了
但是如果两个长度相等的全0段出现在不同位置 那么就是一个坑点了
0:0:0:x:x:x:x:x —->::x:x:x:x:x
x:x:x:0:0:0:x:x—>x:x:x::x:x
发现没有!省略中间的会短一个:!
明白了这一点代码就好写了
#include<algorithm> #include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<ctime> #include<map> #include<stack> #include<set> #include<cstring> #include<sstream> #include<queue> #include<iomanip> using namespace std; typedef long long ll; int Toint(string s) { int ans = 0; int k = 1; for (int i = 15; i >= 0; --i) { ans += k * (s[i] - '0'); k *= 2; } return ans; } int a[10]; void Solve(string s) { memset(a, 0, sizeof(a)); for (int i = 0; i <= 112; i += 16) { string t = s.substr(i, 16); a[i / 16] = Toint(t); } int k = 0; int pos = -1; int mx = 2; for (int i = 0; i < 8; ++i) { if (a[i] == 0) { k++; if (k >= mx) { if (pos == 0 || pos + mx - 1 == 7) { pos = i - k + 1; mx = k; } else { if (k != mx) { pos = i - k + 1; mx = k; } else { if (i - k + 1 == 0 || i == 7) { if (pos == -1 || pos == 0) pos = i - k + 1; //continue; } else { pos = i - k + 1; mx = k; } } } } } else k = 0; } int f = 1; for (int i = 0; i < 8; ++i) { if (f) { f = 0; if (i == pos) { cout << "::"; i += mx; i--; f = 1; } else cout << hex << a[i]; } else { if (i == pos) { cout << "::"; i += mx; i--; f = 1; } else { cout << ':'; cout << hex << a[i]; } } } cout << endl; } int main() { int T; cin >> T; for (int i = 1; i <= T; i++) { string s; cin >> s; printf("Case #%d: ", i); Solve(s); } return 0; }