华为OD机试真题---增强的strstr

题目描述

C语言中的strstr函数用于在字符串haystack中查找第一次出现字符串needle的位置,如果未找到则返回NULL。现在要求实现一个增强的strstr函数,该函数可以使用带可选段的字符串来模糊查询。可选段使用[]标识,表示该位置可以是可选段中的任意一个字符即可满足匹配条件。例如,"a[bc]"可以匹配"ab""ac"


输入描述

输入包含两个字符串,分别是源字符串和目标字符串,以空格分隔。


输出描述

输出一个整数,表示匹配子字符串在源字符串中的起始位置(从0开始计数)。如果没有匹配,则输出-1。


注意事项

  • 源字符串中不包含[]
  • 目标字符串中的[]成对出现,且不会嵌套。
  • 输入的字符串长度在[1,100]之间。

解题思路

  1. 解析目标字符串:将目标字符串解析为模式数组,其中普通字符直接保存,可选字符用集合(如Python中的set)表示。
  2. 在源字符串中查找匹配:遍历源字符串,对每个位置尝试匹配模式数组。如果完全匹配,返回当前位置;如果不匹配,继续下一个位置。
  3. 返回结果:如果遍历完源字符串仍未找到匹配,返回-1。

示例

输入:abcd b[cd]

输出:1

解释:在源字符串"abcd"中,"bc"子字符串的起始位置是1,而"b[cd]"可以匹配"bc""bd"

参考代码(java)


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class EnhancedStrstr {

        /**
 * 增强的字符串匹配函数
 * 
 * @param haystack 要搜索的字符串
 * @param needle 要查找的模式字符串
 * @return 模式字符串在搜索字符串中的首次出现的起始索引;如果搜索字符串不包含模式字符串,则返回 -1
 * 
 * 函数说明:
 * 本函数尝试在搜索字符串(haystack)中找到模式字符串(needle)的首次出现。
 * 它将模式字符串解析为字符和字符集列表,以便高效匹配。
 * 然后遍历搜索字符串,将解析后的模式与搜索字符串的子串进行比较。
 * 如果找到匹配项,则返回匹配项的起始索引;如果遍历整个字符串后未找到匹配项,则返回 -1。
 */
public static int enhancedStrstr(String haystack, String needle) {
    // 将 'needle' 字符串解析为字符和字符集列表
    List<Object> pattern = parsePattern(needle);

    // 在 'haystack' 中查找匹配项
    for (int i = 0; i <= haystack.length() - patternLength(pattern); i++) {
        if (matchesPattern(haystack, i, pattern)) {
            // 如果找到匹配项,返回当前索引
            return i;
        }
    }

    // 如果未找到匹配项,返回 -1
    return -1;
}

    /**
     * 解析指定字符串中的模式,将普通字符和方括号内的字符选项分别存储为列表项。
     *
     * @param needle 待解析的字符串,包含方括号表示的字符选项。
     * @return 返回一个List,其中包含字符和字符选项的Set。
     * @throws IllegalArgumentException 如果字符串格式不正确,例如方括号未闭合或嵌套。
     */
    private static List<Object> parsePattern(String needle) {
        List<Object> pattern = new ArrayList<>();
        StringBuilder currentOption = null;

        // 遍历输入字符串中的每个字符
        for (char c : needle.toCharArray()) {
            // 处理方括号内选项的开始
            if (c == '[') {
                // 如果当前已有未处理的选项,说明嵌套使用了方括号,抛出异常
                if (currentOption != null) {
                    throw new IllegalArgumentException("Invalid needle string: Nested [] not allowed");
                }
                // 开始新的选项构建
                currentOption = new StringBuilder();
            }
            // 处理方括号内选项的结束
            else if (c == ']') {
                // 如果当前没有正在构建的选项,说明方括号配对不正确,抛出异常
                if (currentOption == null) {
                    throw new IllegalArgumentException("Invalid needle string: Unmatched ]");
                }
                // 将当前选项字符串转换为字符集合并添加到模式中
                Set<Character> options = new HashSet<>();
                for (char optionChar : currentOption.toString().toCharArray()) {
                    options.add(optionChar);
                }
                pattern.add(options);
                currentOption = null;
            }
            // 处理普通字符或当前选项内的字符
            else {
                // 根据当前选项构建状态决定是追加到选项中还是作为普通字符添加到模式中
                if (currentOption != null) {
                    currentOption.append(c);
                } else {
                    pattern.add(c);
                }
            }
        }

        // 检查是否有未闭合的方括号,如果有,抛出异常
        if (currentOption != null) {
            throw new IllegalArgumentException("Invalid needle string: Unclosed []");
        }

        return pattern;
    }


    /**
     * 计算匹配模式的长度
     * 匹配模式可以包含字符和字符集,其中字符集是一个集合,匹配时可以是集合中的任何一个字符
     * 此方法用于确定模式的总长度,字符集只占用一个位置,无论其包含多少个字符
     *
     * @param pattern 匹配模式,可以包含Character类型的字符和Set<Character>类型的字符集
     * @return 返回模式的总长度
     */
    private static int patternLength(List<Object> pattern) {
        // 初始化长度计数器
        int length = 0;
        // 遍历匹配模式中的每个元素
        for (Object p : pattern) {
            // 如果元素是字符,长度增加1
            if (p instanceof Character) {
                length++;
            } else if (p instanceof Set) {
                // 如果元素是字符集,也视为一个整体,长度增加1
                // 字符集只占用一个位置,但匹配时可以是集合中的任何一个字符
                length++;
            }
        }
        // 返回计算得到的模式长度
        return length;
    }


    /**
     * 使用指定模式匹配从字符串的特定位置开始的子字符串是否符合该模式
     * 
     * @param haystack 被搜索的字符串
     * @param startIndex 开始匹配的位置索引
     * @param pattern 包含字符和选项集的模式列表
     * @return 如果模式匹配成功则返回true,否则返回false
     */
    private static boolean matchesPattern(String haystack, int startIndex, List<Object> pattern) {
        // 遍历模式中的每个元素,尝试与字符串中的字符匹配
        for (int j = 0; j < pattern.size(); j++) {
            Object p = pattern.get(j);
            // 检查剩余的字符串长度是否足以完成模式的匹配
            if (startIndex + j >= haystack.length()) {
                return false; // haystack剩余长度不足以匹配整个模式
            }
            char haystackChar = haystack.charAt(startIndex + j);
            // 根据模式元素的类型,进行字符精确匹配或选项集匹配
            if (p instanceof Character) {
                // 如果模式元素是字符类型,比较字符是否完全相同
                if (haystackChar != (char) p) {
                    return false;
                }
            } else if (p instanceof Set) {
                Set<Character> options = (Set<Character>) p;
                // 如果模式元素是选项集类型,检查字符是否属于选项集
                if (!options.contains(haystackChar)) {
                    return false;
                }
            }
        }
        return true; // 所有字符都匹配
    }


    public static void main(String[] args) {
        String haystack = "abcd";
        String needle = "b[cd]";
        System.out.println(enhancedStrstr(haystack, needle)); // 应该输出 1
    }
}

运行示例解析

输入

String haystack = "abcd";
String needle = "b[cd]";

解析过程

  1. 解析 needle 字符串

    • needle 字符串 "b[cd]"parsePattern 方法解析为一个包含两个元素的列表 pattern
    • 第一个元素是字符 'b',直接作为列表中的一个元素。
    • 第二个元素是一个 Set<Character>,包含字符 'c''d',因为它们在字符集 [cd] 中。
  2. 计算模式长度

    • patternLength(pattern) 方法计算并返回 2,因为虽然字符集 [cd] 包含两个字符,但在模式匹配中它只占用一个位置。
  3. haystack 中查找匹配项

    • enhancedStrstr 方法中的循环从 haystack 的索引 0 开始,尝试找到与 pattern 匹配的子串。
    • startIndex0 时,haystack 的子串 "a" 不与 pattern 的第一个元素 'b' 匹配,因此继续下一个迭代。
    • startIndex1 时,haystack 的子串 "b"pattern 的第一个元素 'b' 匹配。
    • 接着检查 haystack 的下一个字符 'c',它位于 pattern 的第二个元素(字符集 [cd])中,因此也匹配。
    • 由于整个 pattern 都匹配了,enhancedStrstr 方法返回 startIndex,即 1

输出

1

这个输出表示在 haystack 字符串 "abcd" 中,从索引 1 开始的位置找到了与 needle 字符串 "b[cd]" 相匹配的子串。注意,这里的匹配是基于 needle 中定义的字符和字符集进行的,即使字符集 [cd] 可以匹配 haystack 中的 'c''d',但由于 needle 的第一个字符是 'b',且它必须紧接在 'c''d' 前面,所以只有在 "b" 后面紧跟着 'c''d' 时才认为匹配成功。在这个例子中,"bcd" 满足了这一条件,尽管 needle 使用字符集 [cd] 来表示 'c''d' 的任意性。

华为OD增强strstr是指华为公司在原有的strstr函数的基础上进行了优化和功能扩展。strstr函数是C语言中的字符串函数,用于在一个字符串中查找目标字符串的位置。华为OD增强strstr在性能和功能方面进行了改进。 首先,在性能方面,华为OD增强strstr使用了优化的算法数据结构。通过对大量数据进行分析和研究,华为工程师们改进了算法,提高了查找的效率。这意味着在使用华为OD增强strstr函数进行字符串查找时,可以更快地定位到目标字符串的位置。 其次,华为OD增强strstr具备了更多的功能。除了在原有的strstr函数的基础上提供字符串查找的功能外,华为OD增强strstr还增加了一些扩展功能。例如,它可以支持多个目标字符串的查找,可以忽略大小写进行查找,可以设置查找的起始位置等。这些新增的功能使得华为OD增强strstr函数更加灵活和实用。 另外,华为OD增强strstr还考虑了一些特殊场景的优化。例如,在处理长字符串时,华为OD增强strstr函数采用了分段查找的方式,减少了内存的占用和查找时间。同时,在处理特殊字符时,华为OD增强strstr函数也考虑到了一些编码以及转义字符的情况,保证了字符串查找的准确性和稳定性。 总而言之,华为OD增强strstr在性能和功能方面进行了改进和扩展,提高了字符串查找的效率和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值