深信服笔试 深信服笔试题 0316

笔试时间:2025年03月16日

历史笔试传送门:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题

题目

毒入侵往往从内网开始,企业为了防范内部违规接入非企业的设备,需要对违规接入企业的设备进行发现,这其中就包括违规接入的NAT设备。NAT设备也叫共享上网设备,它对外表现为只有一个IP地址,而内部可以接入很多个物理设备。典型的家庭拨号上网场景,拨号之后路由器对外使用统一IP,而内部接入的多个设备则使用内网私有IP。为了检测企业内部是否接入NAT设备,深信服同事研究发现,虽然经过NAT后设备只有一个IP地址,但它们还有一些可以识别内部物理设备的独特指纹存在,可以根据统计某个IP下 一段时间独特指纹的数量来判断设备是否为NAT设备。独特的指纹我们统一使用A、B、C、D等来表示。同一个IP下的指纹序列存在以下示例。AAAAAAAAAAAA 

如上,IP一直只有一个指纹A,则输出终端数量1。

AAAAAABBBBBB 

如上,考虑DHCP场景。A设备释放IP之后正好被B设备使 用,表现为这个IP下原来全是A的指纹,后面切换全是B的 指纹,则输出终端数量依旧日为1。 

AAAAAABBBBBBBCCCCCCCC 

如上,按照上面的解释,DHCP场景,一个IP下的指纹从 A切换为B再切换为C,输出的终端数量依旧日为1。AAABBBAAAAAAAA 

如上,A指纹后是B再是A,分了提升检测的可靠性,需要 检测某类指纹是否交替出现,此例中A指纹交替1次,而B指纹 仅出现1次没有交替,则认为只有1个可信终端A。

АААВВССАССССВВА 

如上,A指纹在一段时间内交替出现2次。B指纹也交替出现1次,C指纹也交替出现1次,则认为A、B、C三个终端在同一时间内共同使用,输出的终端数量为3。

现存在交替次数n(n表示终端指纹至少交替多少次才算1个可信终端,比如上面的例子中交替1次即算1个可信终端,也可以是2或者3),m组某个iP特定时间段内的指纹序列,请输出每组指纹对应的可信终端数量是多少?

输入描述

第一行输入两个正整数n,m(1 <= n <= 4, 1 <= m <= 1000),其中n表示终端指纹至少

需要交替多少次才可算作1个可信终端,接下来m行,每行输入某个IP的一组指纹序列。指纹序列的格式如下

AAAAAAA

AAABBBCCCDDD

ABBACCBDDA

输出描述

对于每一个指纹序列,输出其可信终端数量。

样例输入

38

DDDDD

XXXXXYYYY

EFFFFQ

BFFFFFFFFBBBFBFFBB

CDDAAAADDCADDDCC

CCDAADDDACCCCDDAAADCDDAAA

EEEQQQBBBQQQEEEBEQBBEEQOBBBB

EEBBAAGGEEBBAAGGEEBBAAGGEBAQ

样例输出

1

1

1

1

1

2

3

4

参考题解

根据题目的意思,一段连续的字符就算作某个主机的一次活动,如果某个主机交替了k次,那么这台主机连续的活动段数应该为(k+1), 因此,使用一个哈希表记录每个主机(其实就是每个字符)的连续的段数,最后判断一下即可。注意肯定会有一台,因此ans = max(1, ans)。

C++:[此代码未进行大量数据的测试,仅供参考]

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        string s;
        cin >> s;
        unordered_map<char, int> cnt;
        int ans = 0;
        int len = s.size();
        for (int i = 0; i < len; ) {
            int j = i;
            while (j < len && s[j] == s[i]) {
                j++;
            }
            cnt[s[i]]++;
            i = j;
        }
        for (auto [k, v] : cnt) {
            if (v - 1 >= n) {
                ans++;
            }
        }
        ans = max(1, ans);
        cout << ans << "\n";
    }
}

Java:[此代码未进行大量数据的测试,仅供参考]

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();  // 阈值
        int m = scanner.nextInt();  // 测试字符串数量
        scanner.nextLine(); // 吃掉换行符

        for (int t = 0; t < m; t++) {
            String s = scanner.nextLine();
            Map<Character, Integer> cnt = new HashMap<>();
            int i = 0;
            int len = s.length();

            while (i < len) {
                int j = i;
                while (j < len && s.charAt(j) == s.charAt(i)) {
                    j++;
                }
                cnt.put(s.charAt(i), cnt.getOrDefault(s.charAt(i), 0) + 1);
                i = j;
            }

            int ans = 0;
            for (Map.Entry<Character, Integer> entry : cnt.entrySet()) {
                if (entry.getValue() - 1 >= n) {
                    ans++;
                }
            }
            System.out.println(Math.max(1, ans));
        }
    }
}

Python:[此代码未进行大量数据的测试,仅供参考]

n, m = map(int, input().split())

for _ in range(m):
    s = input()
    cnt = {}
    i = 0
    length = len(s)

    while i < length:
        j = i
        while j < length and s[j] == s[i]:
            j += 1
        cnt[s[i]] = cnt.get(s[i], 0) + 1
        i = j

    ans = sum(1 for v in cnt.values() if v - 1 >= n)
    print(max(1, ans))

第二题

题目

定义数字的循环右移操作,所有的数字往右移位,最低位的 会移动到高位,如:9527循环右移1位变成79529527循环右移3位变成5279 给定一个正整数n(n可能会很大),求n通过循环右移的所有方案中,能达到的最大值是多少

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务