20200523滴滴2018计算机视觉研发算法订正(find substr) 字符串操作

1.给定一个非空字符串, 按照如下方式编码, 使得编码后长度最小, 返回编码后的长度:
编码规则为: k[encoding_string], 表示重复k次encoding_strng,
例如’abcdefabcdefabc’可表示为’2[abcdef]abc’, 但是’aaa’仅能编码成’aaa’,
因为len(‘3[a]’)>len(‘aaa’).
补充:

  1. k为正整数, []内的encoding_string不得含有空格不得为空;
  2. []内的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]’;
  3. 输入字符串为全小写英文字母, 长度<=160;
  4. 如果编码后长度没有更小, 则保留原有字符串;

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;
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值