1.给定一个非空字符串, 按照如下方式编码, 使得编码后长度最小, 返回编码后的长度:
编码规则为: k[encoding_string], 表示重复k次encoding_strng,
例如’abcdefabcdefabc’可表示为’2[abcdef]abc’, 但是’aaa’仅能编码成’aaa’,
因为len(‘3[a]’)>len(‘aaa’).
补充:
- k为正整数, []内的encoding_string不得含有空格不得为空;
- []内的encoding_string 本身可以为编码过的字符串, 例如’abcdabcdeabcdabcde’ 可以编码为 ‘2[abcdabcde]’(编码后长度从18减少到12), []内的’abcdabcde’又可以编码为 ‘2[abcd]e’, 最终编码为 ‘2[2[abcd]e]’, 编码后长度为11, 应返回11; 这个编码路径也能是: ‘abcdabcdeabcdabcde’ -> ‘2[abcd]e2[abcd]e’ -> ‘2[2[abcd]e]’;
- 输入字符串为全小写英文字母, 长度<=160;
- 如果编码后长度没有更小, 则保留原有字符串;
22.无类别域间路由(CIDR)是一个用于对IPV4地址进行分类表述的方法。CIDR 路由描述的IP地址组的子网mask长度是可变长度, 例如10.0.0.0/22 表示前22位和10.0.0.0相同的网络地址都被覆盖, 22包含了10.0这前两个字段(0-7位,8-15位)和第三个字段的前6位(16-21,即0b000000**), 涵盖了 10.0.0., 10.0.1., 10.0.2., 10.0.3. 四组ip地址. 在此前提下请实现IP网络中的一个常用的去重操作: 给定一系列 CIDR 路由地址, 其中没有完全等价的路由, 去掉被重复表示的 CIDR 路由, 即去掉已经被其他CIDR路由表示覆盖的路由地址. 例如 10.0.1.1/32 已经被 10.0.0.0/22覆盖了, 如果路由列表中已经有了后者, 就可以去掉前者.
这道题中的字符串操作
注意1:定义结构体
struct ip { // 用一各4个int的vector来保存ip
vector<int> data;
ip() {
data = vector<int>(4);
}
};
注意2:用结构体做数据类型定义结构体
struct cidr { // 用起始和结束ip来表示cidr
ip start; // 起始ip地址
ip end; // 结束ip地址
};
注意3:find函数
str为一字符串变量 str.find(’.’,4);
find的参数 为 要寻找的字符 以及查找的起始位置 find函数的返回值是找到的目标字符位置下标
注意4:找到下标之后 要看使用下标时下标是否有效
while(e!=string::npos)
注意4: vector()容器的back() 表示返回当前vector末尾元素的引用(引用是值不是下标 要注意)
.begin() .end() .front() .back()
但是 end() 是指向最后一个元素的下一个位置的
注意5:stoi()函数
作用:把字符串转换成int输出
注意6: s.substr()函数 返回子串的拷贝
这个子串呢 就是
substr(pos,n) pos表示的是开始拷贝的位置 n表示拷贝的长度 如果不加n就会默认拷贝整个串 就变成了烤串
本体的完整代码为
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <hash_map>
using namespace std;
struct ip { // 用一各4个int的vector来保存ip
vector<int> data;
ip() {
data = vector<int>(4);
}
};
struct cidr { // 用起始和结束ip来表示cidr
ip start; // 起始ip地址
ip end; // 结束ip地址
};
cidr str2cidr(const string & str) { // 将字符串转换成cidr
int s = 0;
int e = str.find('.', s);
cidr res;
int i = 0;
while (e != string::npos) {
res.start.data[i++] = stoi(str.substr(s, e - s));
s = e + 1;
e = str.find('.', s);
}
e = str.find('/');
res.start.data.back() = stoi(str.substr(s, e - s));
int len = stoi(str.substr(e + 1, str.size() - e));
res.end = res.start;
int p1 = len / 8;
int rest = len % 8; // 还有几位相同
for (int i = p1; i < 4; ++i) {
res.start.data[i] &= (255 << (8 - rest));
res.end.data[i] |= ~(-1 << (8 - rest));
rest = 0;
}
return res;
}
bool LT(ip a, ip b) { // 判断ip的大小
for (int i = 0; i < 4; ++i) {
if (a.data[i] <= b.data[i]) {
continue;
} else {
return false;
}
}
return true;
}
bool GT(ip a, ip b) {
for (int i = 0; i < 4; ++i) {
if (a.data[i] >= b.data[i]) {
continue;
} else {
return false;
}
}
return true;
}
bool cidr_contain(cidr a, cidr b) { // 判断cidr a 是否包含 cidr b
return a.start.data[0] == b.start.data[0] & LT(a.start, b.start) && GT(a.end, b.end);
}
void process(const string & str, vector<string> & cidrs_str, vector<cidr> & cidrs, int & erased) {
cidr t = str2cidr(str);
for (int i = 0; i < cidrs.size(); ++i) {
if (cidrs_str[i].size() > 0) {
if (cidr_contain(cidrs[i], t)) {
return;
}
if (cidr_contain(t, cidrs[i])) {
cidrs_str[i] = "";
erased++;
}
}
}
cidrs_str.emplace_back(str);
cidrs.emplace_back(t);
}
int main() {
string str = "172.24.68.0/24";
int n = 0;
while (cin >> n) {
vector<string> cidrs_str; // 为空则无效
vector<cidr> cidrs;
int erased = 0;
while (n--) {
cin >> str;
process(str, cidrs_str, cidrs, erased);
}
cout << cidrs.size() - erased << endl;
for (auto item : cidrs_str) {
if (item.size() > 0) {
cout << item << endl;
}
}
}
}