解题思路
-
对每行输入进行处理:
- 按空格分割得到 IP 地址和子网掩码
- 分别验证 IP 地址和子网掩码的合法性
-
IP 地址合法性检查:
- 按点分割成 4 个数字
- 每个数字必须在 0-255 范围内
- 检查是否属于私有 IP 范围
-
子网掩码合法性检查:
- 按点分割成 4 个数字
- 每个数字必须在 0-255 范围内
- 转换成二进制后必须是连续的 1 后跟连续的 0
-
IP 地址分类:
- A类:1.0.0.0 - 126.255.255.255
- B类:128.0.0.0 - 191.255.255.255
- C类:192.0.0.0 - 223.255.255.255
- D类:224.0.0.0 - 239.255.255.255
- E类:240.0.0.0 - 255.255.255.255
代码
#include <bits/stdc++.h>
using namespace std;
// 思路:(首先排除0.*.*.* 和127.*.*.* 的IP地址
// ,因为这种IP地址不属于任何一类需要计数的类型)
// 1.判断子网掩码是否正确:错误属于IP或掩码错误情况,相应计数加1,继续下一条字符串判断,重新开始1;正确进入2
// 2.此时掩码正确,判断IP地址是否正确:错误属于IP或掩码错误情况,相应计数加1,继续下一条字符串判断,重新开始1;正确进入3
// 3.此时IP正确,判段属于A/B/C/D/E哪类地址,同时判断是否属于私有地址,相应计数加1,继续下一条字符串判断,重新开始1
int main() {
string t;
int na = 0;
int nb = 0;
int nc = 0;
int nd = 0;
int ne = 0;
int ni = 0; // number of invalid;
int np = 0; // number of private;
while (getline(cin, t)) {
int len = t.length();
int tilde = t.find('~'); // seperate: ~
string s_ip = t.substr(0, tilde);
string s_mk = t.substr(tilde + 1, len - tilde - 1);
// Step-1: Ignoring 0.*.*.* and 127.*.*.*;
int ipPoint1 = s_ip.find('.');
string ip1 = s_ip.substr(0, ipPoint1);
if (ip1 == "0" || ip1 == "127") {
continue;
}
// 判断子网掩码是否正确
int maskPoint1 = s_mk.find('.'); // 查找子网掩码中第1个点
string mask1 = s_mk.substr(0, maskPoint1);
if (mask1 == "" || stoi(mask1) > 255) { // 不能为空位
ni++;
continue;
}
bitset<8> bMask1(
stoi(mask1)); // 将字符串形式的数字转为整型后,获取其8位二进制值
int maskPoint2 = s_mk.find(
'.',
maskPoint1 + 1); // 从maskPoint1 + 1位置开始,查找子网掩码中第2个点
string mask2 = s_mk.substr(maskPoint1 + 1, maskPoint2 - maskPoint1 - 1);
if (mask2 == "" || stoi(mask2) > 255) { // 不能为空位
ni++;
continue;
}
bitset<8> bMask2(stoi(mask2));
int maskPoint3 =
s_mk.find('.', maskPoint2 + 1); // 查找子网掩码中第一个点
string mask3 = s_mk.substr(maskPoint2 + 1, maskPoint3 - maskPoint2 - 1);
if (mask3 == "" || stoi(mask3) > 255) { // 不能为空位
ni++;
continue;
}
bitset<8> bMask3(stoi(mask3));
string mask4 =
s_mk.substr(maskPoint3 + 1, s_mk.length() - maskPoint3 - 1);
if (mask4 == "" || stoi(mask4) > 255) { // 不能为空位
ni++;
continue;
}
bitset<8> bMask4(stoi(mask4));
// Error-Mask: All zero or all one;
if (bMask1.count() + bMask2.count() + bMask3.count() + bMask4.count() ==
32 ||
bMask1.count() + bMask2.count() + bMask3.count() + bMask4.count() ==
0) {
ni++;
continue;
}
int vMask[32] = {0}; // 将二进制的子网掩码放入整型数组vMask,用于判断子网掩码中的连续1
for (int i = 0; i < 32; i++) {
if (i >= 0 && i <= 7) {
vMask[i] = bMask1[7 - i];
} else if (i >= 8 && i <= 15) {
vMask[i] = bMask2[7 - i + 8];
} else if (i >= 16 && i <= 23) {
vMask[i] = bMask3[7 - i + 16];
} else if (i >= 24 && i < 31) {
vMask[i] = bMask4[7 - i + 24];
}
}
bool ErrorContinue =
false; // 判断是否存在连续的1 ,不连续1非法 i,j 双指针判断
for (int i = 0, j = 1; j < 32;) {
if (vMask[i] == 0 &&
vMask[j] ==
1) { // 对一串子网掩码而言,出现 ****01***即是非法的掩码
ErrorContinue = true;
break;
}
i++;
j++;
}
if (ErrorContinue) {
ni++;
continue;
}
// Step-3: Verify IP correctness;
if (ip1 == "" || stoi(ip1) > 255) {
ni++;
continue;
}
int ipPoint2 = s_ip.find('.', ipPoint1 + 1);
string ip2 = s_ip.substr(ipPoint1 + 1, ipPoint2 - ipPoint1 - 1);
if (ip2 == "" || stoi(ip2) > 255) {
ni++;
continue;
}
int ipPoint3 = s_ip.find('.', ipPoint2 + 1);
string ip3 = s_ip.substr(ipPoint2 + 1, ipPoint3 - ipPoint2 - 1);
if (ip3 == "" || stoi(ip3) > 255) {
ni++;
continue;
}
string ip4 = s_ip.substr(ipPoint3 + 1, s_ip.length() - ipPoint3 - 1);
if (ip4 == "" || stoi(ip4) > 255) {
ni++;
continue;
}
// Step-4: All clear, classify IP to A-B-C-D-E;
int judge1 = stoi(ip1);
int judge2 = stoi(ip2);
if (judge1 >= 1 && judge1 <= 126) { // A 类
na++;
if (judge1 == 10) {
np++;
}
} else if (judge1 >= 128 && judge1 <= 191) { // B 类
nb++;
if (judge1 == 172 && judge2 >= 16 && judge2 <= 31) {
np++;
}
} else if (judge1 >= 192 && judge1 <= 223) { // C 类
nc++;
if (judge2 == 168) {
np++;
}
} else if (judge1 >= 224 && judge1 <= 239) { // D 类
nd++;
} else if (judge1 >= 240 && judge1 <= 255) { // E 类
ne++;
}
}
cout << na << " " << nb << " " << nc << " " << nd << " " << ne << " " << ni
<< " " << np << " " << endl;
}
import java.util.Scanner;
import java.util.BitSet;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int na = 0; // A类IP数量
int nb = 0; // B类IP数量
int nc = 0; // C类IP数量
int nd = 0; // D类IP数量
int ne = 0; // E类IP数量
int ni = 0; // 错误IP数量
int np = 0; // 私有IP数量
while (sc.hasNextLine()) {
String t = sc.nextLine();
int tilde = t.indexOf('~');
String s_ip = t.substring(0, tilde);
String s_mk = t.substring(tilde + 1);
// Step-1: 忽略 0.*.*.* 和 127.*.*.* 的IP地址
int ipPoint1 = s_ip.indexOf('.');
String ip1 = s_ip.substring(0, ipPoint1);
if (ip1.equals("0") || ip1.equals("127")) {
continue;
}
// 判断子网掩码是否正确
int maskPoint1 = s_mk.indexOf('.');
String mask1 = s_mk.substring(0, maskPoint1);
try {
if (mask1.isEmpty() || Integer.parseInt(mask1) > 255) {
ni++;
continue;
}
BitSet bMask1 = BitSet.valueOf(new long[]{Integer.parseInt(mask1)});
int maskPoint2 = s_mk.indexOf('.', maskPoint1 + 1);
String mask2 = s_mk.substring(maskPoint1 + 1, maskPoint2);
if (mask2.isEmpty() || Integer.parseInt(mask2) > 255) {
ni++;
continue;
}
BitSet bMask2 = BitSet.valueOf(new long[]{Integer.parseInt(mask2)});
int maskPoint3 = s_mk.indexOf('.', maskPoint2 + 1);
String mask3 = s_mk.substring(maskPoint2 + 1, maskPoint3);
if (mask3.isEmpty() || Integer.parseInt(mask3) > 255) {
ni++;
continue;
}
BitSet bMask3 = BitSet.valueOf(new long[]{Integer.parseInt(mask3)});
String mask4 = s_mk.substring(maskPoint3 + 1);
if (mask4.isEmpty() || Integer.parseInt(mask4) > 255) {
ni++;
continue;
}
BitSet bMask4 = BitSet.valueOf(new long[]{Integer.parseInt(mask4)});
// 检查掩码是否全0或全1
int totalOnes = bMask1.cardinality() + bMask2.cardinality() +
bMask3.cardinality() + bMask4.cardinality();
if (totalOnes == 32 || totalOnes == 0) {
ni++;
continue;
}
// 检查掩码的连续性
int[] vMask = new int[32];
for (int i = 0; i < 8; i++) {
vMask[i] = bMask1.get(7 - i) ? 1 : 0;
vMask[i + 8] = bMask2.get(7 - i) ? 1 : 0;
vMask[i + 16] = bMask3.get(7 - i) ? 1 : 0;
vMask[i + 24] = bMask4.get(7 - i) ? 1 : 0;
}
boolean errorContinue = false;
for (int i = 0; i < 31; i++) {
if (vMask[i] == 0 && vMask[i + 1] == 1) {
errorContinue = true;
break;
}
}
if (errorContinue) {
ni++;
continue;
}
// 验证IP地址的正确性
if (ip1.isEmpty() || Integer.parseInt(ip1) > 255) {
ni++;
continue;
}
int ipPoint2 = s_ip.indexOf('.', ipPoint1 + 1);
String ip2 = s_ip.substring(ipPoint1 + 1, ipPoint2);
if (ip2.isEmpty() || Integer.parseInt(ip2) > 255) {
ni++;
continue;
}
int ipPoint3 = s_ip.indexOf('.', ipPoint2 + 1);
String ip3 = s_ip.substring(ipPoint2 + 1, ipPoint3);
if (ip3.isEmpty() || Integer.parseInt(ip3) > 255) {
ni++;
continue;
}
String ip4 = s_ip.substring(ipPoint3 + 1);
if (ip4.isEmpty() || Integer.parseInt(ip4) > 255) {
ni++;
continue;
}
// IP分类统计
int judge1 = Integer.parseInt(ip1);
int judge2 = Integer.parseInt(ip2);
if (judge1 >= 1 && judge1 <= 126) { // A类
na++;
if (judge1 == 10) {
np++;
}
} else if (judge1 >= 128 && judge1 <= 191) { // B类
nb++;
if (judge1 == 172 && judge2 >= 16 && judge2 <= 31) {
np++;
}
} else if (judge1 >= 192 && judge1 <= 223) { // C类
nc++;
if (judge1 == 192 && judge2 == 168) {
np++;
}
} else if (judge1 >= 224 && judge1 <= 239) { // D类
nd++;
} else if (judge1 >= 240 && judge1 <= 255) { // E类
ne++;
}
} catch (NumberFormatException e) {
ni++;
continue;
}
}
System.out.println(na + " " + nb + " " + nc + " " + nd + " " + ne + " " + ni + " " + np);
sc.close();
}
}
def main():
na = nb = nc = nd = ne = ni = np = 0 # 初始化计数器
while True:
try:
t = input().strip()
tilde = t.find('~')
s_ip = t[:tilde]
s_mk = t[tilde + 1:]
# Step-1: 忽略 0.*.*.* 和 127.*.*.* 的IP地址
ipPoint1 = s_ip.find('.')
ip1 = s_ip[:ipPoint1]
if ip1 == "0" or ip1 == "127":
continue
# 判断子网掩码是否正确
try:
maskPoint1 = s_mk.find('.')
mask1 = s_mk[:maskPoint1]
if not mask1 or int(mask1) > 255:
ni += 1
continue
bMask1 = bin(int(mask1))[2:].zfill(8)
maskPoint2 = s_mk.find('.', maskPoint1 + 1)
mask2 = s_mk[maskPoint1 + 1:maskPoint2]
if not mask2 or int(mask2) > 255:
ni += 1
continue
bMask2 = bin(int(mask2))[2:].zfill(8)
maskPoint3 = s_mk.find('.', maskPoint2 + 1)
mask3 = s_mk[maskPoint2 + 1:maskPoint3]
if not mask3 or int(mask3) > 255:
ni += 1
continue
bMask3 = bin(int(mask3))[2:].zfill(8)
mask4 = s_mk[maskPoint3 + 1:]
if not mask4 or int(mask4) > 255:
ni += 1
continue
bMask4 = bin(int(mask4))[2:].zfill(8)
# 检查掩码是否全0或全1
total_ones = (bMask1 + bMask2 + bMask3 + bMask4).count('1')
if total_ones == 0 or total_ones == 32:
ni += 1
continue
# 检查掩码的连续性
vMask = []
for b in [bMask1, bMask2, bMask3, bMask4]:
vMask.extend([int(x) for x in b])
error_continue = False
for i in range(31):
if vMask[i] == 0 and vMask[i + 1] == 1:
error_continue = True
break
if error_continue:
ni += 1
continue
# 验证IP地址的正确性
if not ip1 or int(ip1) > 255:
ni += 1
continue
ipPoint2 = s_ip.find('.', ipPoint1 + 1)
ip2 = s_ip[ipPoint1 + 1:ipPoint2]
if not ip2 or int(ip2) > 255:
ni += 1
continue
ipPoint3 = s_ip.find('.', ipPoint2 + 1)
ip3 = s_ip[ipPoint2 + 1:ipPoint3]
if not ip3 or int(ip3) > 255:
ni += 1
continue
ip4 = s_ip[ipPoint3 + 1:]
if not ip4 or int(ip4) > 255:
ni += 1
continue
# IP分类统计
judge1 = int(ip1)
judge2 = int(ip2)
if 1 <= judge1 <= 126: # A类
na += 1
if judge1 == 10:
np += 1
elif 128 <= judge1 <= 191: # B类
nb += 1
if judge1 == 172 and 16 <= judge2 <= 31:
np += 1
elif 192 <= judge1 <= 223: # C类
nc += 1
if judge1 == 192 and judge2 == 168:
np += 1
elif 224 <= judge1 <= 239: # D类
nd += 1
elif 240 <= judge1 <= 255: # E类
ne += 1
except ValueError:
ni += 1
continue
except EOFError:
break
print(f"{na} {nb} {nc} {nd} {ne} {ni} {np}")
if __name__ == "__main__":
main()
算法及复杂度
- 算法:字符串处理 + 位运算
- 时间复杂度:
,其中 n 是输入的行数
- 空间复杂度:
,只需要常数级别的额外空间