题目的主要信息:

  • 利用子网掩码可以判断两台主机是否中同一子网中。若两台主机的IP地址分别与它们的子网掩码相“与”后的结果相同,则说明这两台主机在同一子网中。
  • 掩码与IP每一段在 0 - 255 之间。掩码的二进制字符串前缀为网络号,都由‘1’组成;后缀为主机号,都由'0'组成

方法一:

按照题目的思路求解。第一步是判断ip地址和掩码的格式是否合法,由题意可知,掩码与IP每一段在 0 - 255 之间,如果有字段小于0或者大于255则直接判为格式非法;若字段都在 0 - 255 之间,判断掩码是否前缀为1,后缀为0,根据归纳推理发现,若0<mask[i]<255,则第i段已经包含0了,那么从第i+1段开始必须全为0,因此若mask[i+1]>0,则格式非法。

格式都合法后,分别对两个ip地址逐段进行AND操作,若结果相同则输出0,否则输出2; alt

具体做法:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> mask(4,0);
    vector<int> ip1(4,0);
    vector<int> ip2(4,0);
    char c;
    while (cin>>mask[0]>>c>>mask[1]>>c>>mask[2]>>c>>mask[3])//输入掩码
    {
        int flag = -1;//结果
        cin>>ip1[0]>>c>>ip1[1]>>c>>ip1[2]>>c>>ip1[3];//第一个ip地址
        cin>>ip2[0]>>c>>ip2[1]>>c>>ip2[2]>>c>>ip2[3];//第二个ip地址
        for(int i=0;i<4;i++)//两个ip地址和掩码每一段都要在0-255之间
        {
            if(mask[i]<0 || mask[i]>255 || ip1[i]<0 || ip1[i]>255 ||ip2[i]<0 || ip2[i]>255)
            {
                flag = 1;//格式非法
                break;
            }
        }
        for(int i=0;i<3;i++)//掩码的网络号全为1,主机号全为0
        {
            if(mask[i]<255 && mask[i+1]>0)
            {
                flag = 1;
                break;
            }
        }
        if(flag==1)//格式非法,输出1
        {
            cout<<flag<<endl;
        }else{
            for(int i=0;i<4;i++)
            {
                if((mask[i]&ip1[i])!=(mask[i]&ip2[i]))//两个ip地址和掩码做AND操作
                {
                    flag = 2;
                    break;
                }else{//AND操作结果不相同
                    flag = 0;
                }
            }
            cout<<flag<<endl;
        }
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(1)O(1)O(1),判断格式合法和进行与操作都只需要常数时间。
  • 空间复杂度:O(1)O(1)O(1),只使用了常数空间。

方法二:

判断格式是否合法的时候可以用正则表达式来判断,((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d).){4}可以判断每个字段是否在0-255。首先把vector类型转换为string,再用regex_match函数和表达式进行匹配,若匹配返回true,否则返回false。进行格式非法判断的时候,用&&进行合并,只要有一个地址不合法,就返回1。

具体做法:

#include<iostream>
#include<vector>
#include<string>
#include<regex>

using namespace std;

int main()
{
    vector<int> mask(4,0);
    vector<int> ip1(4,0);
    vector<int> ip2(4,0);
    regex pattern("((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\.){4}");//匹配0.0.0.0.-255.255.255.255.的正则表达式
    char c;
    while (cin>>mask[0]>>c>>mask[1]>>c>>mask[2]>>c>>mask[3])//输入掩码
    {
        int flag = -1;//结果
        cin>>ip1[0]>>c>>ip1[1]>>c>>ip1[2]>>c>>ip1[3];//第一个ip地址
        cin>>ip2[0]>>c>>ip2[1]>>c>>ip2[2]>>c>>ip2[3];//第二个ip地址
        string str_mask,str_ip1,str_ip2;
        for(int i=0;i<4;i++){
            str_mask+=to_string(mask[i])+'.';
            str_ip1+=to_string(ip1[i])+'.';
            str_ip2+=to_string(ip2[i])+'.';
        }
        if((regex_match(str_mask,pattern)&&regex_match(str_ip1,pattern)&&regex_match(str_ip2,pattern))==false)
        {
            flag=1;
        }
        for(int i=0;i<3;i++)//掩码的网络号全为1,主机号全为0
        {
            if(mask[i]<255 && mask[i+1]>0)
            {
                flag = 1;
                break;
            }
        }
        if(flag==1)//格式非法,输出1
        {
            cout<<flag<<endl;
        }else{
            for(int i=0;i<4;i++)
            {
                if((mask[i]&ip1[i])!=(mask[i]&ip2[i]))//两个ip地址和掩码做AND操作
                {
                    flag = 2;
                    break;
                }else{//AND操作结果相同
                    flag = 0;
                }
            }
            cout<<flag<<endl;
        }
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(1)O(1)O(1),判断格式合法和进行与操作都只需要常数时间。
  • 空间复杂度:O(1)O(1)O(1),只使用了常数空间。