华为OD机试 - 最长子字符串的长度(二) (Java 2024 D卷 100分)

在这里插入图片描述

华为OD机试 2024D卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

给你一个字符串 s,字符串 s 首尾相连成一个环形,请你在环中找出 ‘l’、‘o’、‘x’ 字符都恰好出现了偶数次最长子字符串 的长度。

二、输入描述

输入是一串小写的字母组成的字符串

三、输出描述

输出是一个整数。

备注:

  • 1 ≤ s.length ≤ 5 * 10^5
  • s 只包含小写英文字母

四、测试用例

测试用例1:

1、输入

alolobo

2、输出

6

3、说明

最长子字符串之一是 “alolob”,它包含 ‘l’、‘o’ 各 2 个,以及 0 个 ‘x’。

测试用例2:

1、输入

looxdolx

2、输出

7

3、说明

最长的子字符串是 “oxdolxl”,由于是首尾连接在一起的,所以最后一个 ‘x’ 和开头的 ‘l’ 是连接在一起的,此字符串包含 2 个 ‘l’、2 个 ‘o’、2 个 ‘x’。

五、解题思路

  1. 将字符串 s 扩展为自身的两倍。这样可以方便地处理环形问题。扩展后的字符串可以模拟环形的效果。
  2. 使用位运算记录字符 ‘l’、‘o’、‘x’ 的出现次数的奇偶性。每个字符对应一个二进制位,出现次数为偶数时该位为0,奇数时为1。
  3. 维护一个前缀和数组,用于记录每个字符在当前位置的出现次数。
  4. 使用哈希表记录每种奇偶状态首次出现的位置。这样可以快速查找当前状态与之前出现的相同状态之间的距离。
  5. 如果一个状态已经出现过,则表示从该状态第一次出现的位置到当前的位置之间的子字符串中,‘l’、‘o’、‘x’ 字符都出现偶数次。
  6. 遍历扩展后的字符串,更新 ‘l’、‘o’、‘x’ 字符的出现次数并计算当前奇偶状态。
  7. 使用哈希表查询当前奇偶状态的首次出现位置,计算子字符串长度,并更新最长子字符串的长度。

六、Java算法源码

public class OdTest {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();

        // 扩展字符串为两倍长度
        String extended = s + s;
        int n = s.length();

        // 哈希表记录奇偶状态首次出现的位置
        Map<Integer, Integer> stateMap = new HashMap<>();
        stateMap.put(0, -1); // 初始状态

        int[] count = new int[3]; // 记录 l, o, x 的出现次数
        int state = 0;
        int maxLength = 0;

        for (int i = 0; i < extended.length(); i++) {
            char c = extended.charAt(i);

            if (c == 'l') {
                count[0]++;
            } else if (c == 'o') {
                count[1]++;
            } else if (c == 'x') {
                count[2]++;
            }

            // 计算当前状态
            state = ((count[0] % 2) << 2) | ((count[1] % 2) << 1) | (count[2] % 2);

            // 记录或更新最长子字符串长度
            if (stateMap.containsKey(state)) {
                int prevIndex = stateMap.get(state);
                if (i - prevIndex > n) break; // 确保子字符串在原字符串长度内
                maxLength = Math.max(maxLength, i - prevIndex);
            } else {
                stateMap.put(state, i);
            }
        }

        System.out.println(maxLength);
    }
}

七、效果展示

1、输入

bcbcbc

2、输出

6

3、说明

字符串 “bcbcbc” 本身就是最长的,因为 ‘l’、‘o’、‘x’ 都出现了 0 次。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 D卷 200分)

🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值