首页 > 其他分享 >华为OD机试真题---增强的strstr

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

时间:2024-09-28 09:20:21浏览次数:3  
标签:字符 needle 匹配 真题 pattern OD 字符串 strstr haystack

题目描述

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' 的任意性。

标签:字符,needle,匹配,真题,pattern,OD,字符串,strstr,haystack
From: https://blog.csdn.net/lbp0123456/article/details/142587073

相关文章

  • Introducing Pricing-Display the Settings of a Condition Type
     step1 step2 step3 step4 step5 step6                           ......
  • S/4HANA Sales-Introducing Pricing
     ObjectiveAftercompletingthislesson,youwillbeableto useconditionsforpricing. ConditionMasterDataNote Learnmoreaboutconditionmasterdataandthestructureofconditionrecords: Theconditiontypedeterminesthecategoryofacond......
  • Codeforces Round 944 (Div. 4) A~G题解
    A\(min\)函数和\(max\)函数的使用,按照格式输出即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<int,int>PII;voidsolve(){intx,y;cin>>x>>y;cout<<min(x,y)<<'......
  • 《Learning Instance-Level Representation for Large-Scale Multi-Modal Pretraining
    系列论文研读目录文章目录系列论文研读目录摘要1.引言2.相关工作3.方法3.1.模型概述3.2.提取以实例为中心的表示法3.3.多模式预培训目标3.4.转移到下游任务4.实验预训练细节4.2.下游任务评价4.2.1零冲击产品分类4.2.2zero-shot图像-文本检索4.2.3零次产品检索4.2.4零......
  • Codeforces Round 973题解(E)
    E.PrefixGCD假设我们从一个空集合\(b\)开始,不断从\(a\)数组中选择一个元素添加到\(b\)集合的尾部,当把\(a\)数组的元素全部添加到\(b\)中后,得到的\(b\)即为所求的rearrange后的\(a\)。结论1:每次选择使得其和当前\(b\)中所有元素的最大公约数最小的那个\(a_i\)加入到\(b\)的末......
  • 字符编码发展史4 — Unicode与UTF-8
    上一篇《字符编码发展史3—GB2312/Big5/GBK/GB18030》我们讲解了ANSI编码中的GB2312/Big5/GBK/GB18030。本篇我们将继续讲解字符编码的第三个发展阶段中的Unicode与UTF-8。2.3.第三个阶段国际化前面提到的第二个阶段,各个国家和地区各自为政,纷纷制定了适用于自己国家语言的字......
  • 丹摩智算(damodel)部署stable diffusion实验
    名词解释:丹摩智算(damodel):是一款带有RTX4090,Tesla-P40等显卡的公有云服务器。stablediffusion:是一个大模型,可支持文生图,图生图,文生视频等功能一.实验目标注册丹摩智算(damodel)账户,创建带有显卡(Tesla-P40)的公有云服务器,系统为:ubuntu22.04_tensorflow2.1,通过ssh协议连接到公......
  • 【Leecode 随笔】C语言版看了不后悔系列持续更新中。。。(四)
    文章目录题目一:实现一个函数,计算两个整数的最大公约数(GCD)题目分析:解题思路:示例代码:代码解析:题目二:实现一个函数,判断一个整数是否为素数题目分析:解题思路:示例代码:代码解析:题目三:实现一个函数,对给定的字符串进行排序(按字母顺序)题目分析:解题思路:示例代码:代码解析:......
  • 【算法题】72. 编辑距离-力扣(LeetCode)
    【算法题】72.编辑距离-力扣(LeetCode)1.题目下方是力扣官方题目的地址72.编辑距离给你两个单词word1和word2,请返回将word1转换成word2所使用的最少操作数。你可以对一个单词进行如下三种操作:插入一个字符删除一个字符替换一个字符示例1:输入:word1="ho......
  • MongoDB
    showdbs//查看所有数据库db//查看当前所在数据库showcollections//查看数据集合use数据库名//切换到指定数据库,如果数据库不存在,则创建数据库db.dropDatabase()//删除当前数据库,要删除哪一个库就切换到哪一个库。db.getCollectionNames()//查询当前库都有哪些集合......