(C卷,200分)- 快速人名查找(Java & JS & Python)

题目描述

给一个字符串,表示用’,’分开的人名。

然后给定一个字符串,进行快速人名查找,符合要求的输出。

快速人名查找要求︰人名的每个单词的连续前几位能组成给定字符串,一定要用到每个单词。

输入描述

第一行是人名,用’,’分开的人名
第二行是 查找字符串

输出描述

输出满足要求的人名

用例

输入 zhang san,zhang san san
zs
输出 zhang san
说明
输入 zhang san san,zhang an sa,zhang hang,zhang seng,zhang sen a
zhas
输出 zhang an sa,zhang seng
说明

题目解析

本题暂时没有想到更好的解法,只能通过暴力法求解。

我的解题思路如下:

比如人名为:zhang seng,前缀缩写为:zhas

首先将人名字符串按照空格分隔为字符串数组,如Sting parts = ["zhang","san"]

前缀缩写定义为 String abbr = "zhas",用一个start指针指向abbr的被检查的字母,初始时start=0,即指向abbr的第0个字母。

然后按照下图逻辑开始进行人名的每个part的前缀部分和abbr的匹配,匹配逻辑如下图所示:

abbr开头字母必须首先要和parts[0]的开头字母匹配,如果无法匹配否则就表示当前人名无法缩写为abbr。

 通过上面图示,我们可以发现,parts[0]每匹配到一个abbr字母,就把下一次的匹配权让给了parts[1],这是为什么呢?

因为,这样可以避免abbr的扫描指针的回溯。啥意思呢?

我们看看下面这个例子:

人名:zhasta san

缩写:zhasa

如果优先parts[0]匹配的话,则必然会走到下面这种情况

然后下一步匹配,就会出问题

此时,我们就需要进行abbr的扫描指针回溯,然后将匹配权交到parts[1]手上。

可能有人觉得这样匹配速度反而会更快一点,但是如果用例是下面这种呢?

  • 人名:zhass san san
  • 缩写:zhass

 即我们可以在一个part中就完成了缩写匹配,但是题目要求所有的单词part都要使用到,此时我们应该如何回溯呢?

这样的回溯操作逻辑将变得十分复杂,且性能不佳。因此我们需要尽量避免abbr的扫描指针回溯行为。

如果,大家对上面部分都理解了,那么本题差不多就搞定了。

上面例子都是两个part的人名,本题并没有说人名由几个part组成,因此我们无法确定要几重for循环解题,此时只能依赖于回溯递归来帮助我们。具体递归逻辑请看代码。

JavaScript算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  const names = (await readline()).split(",");
  const abbr = await readline();
  console.log(getResult(names, abbr));
})();

function getResult(names, abbr) {
  const ans = [];

  for (let name of names) {
    const parts = name.split(" ");

    if (parts.length > abbr.length) continue;

    if (recursive(parts, 0, abbr, 0)) {
      ans.push(name);
    }
  }

  return ans.join(",");
}

/**
 *
 * @param {*} parts 人名组成
 * @param {*} parts_index 人名被匹配的组成部分的索引位置
 * @param {*} abbr 人名缩写
 * @param {*} abbr_index 缩写被匹配的字符的索引位置
 * @returns 当前人名name是否匹配对应缩写abbr
 */
function recursive(parts, parts_index, abbr, abbr_index) {
  if (abbr_index >= abbr.length) {
    // 如果缩写被匹配完,且人名组成也匹配到最后一个,则说明当前人名可以匹配对应缩写
    return parts_index >= parts.length;
  }

  // 如果缩写尚未匹配完,但是人名组成已经匹配完,则说明当前人名无法匹配对应缩写
  if (parts_index >= parts.length) {
    return false;
  }

  const part_name = parts[parts_index];

  for (let j = 0; j < part_name.length; j++) {
    // 如果当前人名组成部分part_name的第 j 个字符 可以 匹配 缩写abbr的第 abbr_index个字符
    if (abbr_index < abbr.length && part_name[j] == abbr[abbr_index]) {
      // 为了保证part_name匹配不回退,此时我们将缩写abbr的第abbr_index+1个字符的匹配权优先交给人名的parts_index + 1部分
      if (recursive(parts, parts_index + 1, abbr, ++abbr_index)) {
        return true;
      }
    } else {
      return false;
    }
  }

  return false;
}

Java算法源码

import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringJoiner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    String[] names = sc.nextLine().split(",");
    String abbr = sc.nextLine();

    System.out.println(getResult(names, abbr));
  }

  public static String getResult(String[] names, String abbr) {
    ArrayList<String> ans = new ArrayList<>();

    for (String name : names) {
      String[] parts = name.split(" ");

      if (parts.length > abbr.length()) continue;

      if (recursive(parts, 0, abbr, 0)) {
        ans.add(name);
      }
    }

    StringJoiner sj = new StringJoiner(",");
    for (String an : ans) {
      sj.add(an);
    }
    return sj.toString();
  }

  /**
   * @param parts 人名组成
   * @param parts_index 人名被匹配的组成部分的索引位置
   * @param abbr 人名缩写
   * @param abbr_index 缩写被匹配的字符的索引位置
   * @return 当前人名name是否匹配对应缩写abbr
   */
  public static boolean recursive(String[] parts, int parts_index, String abbr, int abbr_index) {
    if (abbr_index >= abbr.length()) {
      // 如果缩写被匹配完,且人名组成也匹配到最后一个,则说明当前人名可以匹配对应缩写
      return parts_index >= parts.length;
    }

    // 如果缩写尚未匹配完,但是人名组成已经匹配完,则说明当前人名无法匹配对应缩写
    if (parts_index >= parts.length) {
      return false;
    }

    String part_name = parts[parts_index];

    for (int j = 0; j < part_name.length(); j++) {
      // 如果当前人名组成部分part_name的第 j 个字符 可以 匹配 缩写abbr的第 abbr_index个字符
      if (abbr_index < abbr.length() && part_name.charAt(j) == abbr.charAt(abbr_index)) {
        // 为了保证part_name匹配不回退,此时我们将缩写abbr的第abbr_index+1个字符的匹配权优先交给人名的parts_index + 1部分
        if (recursive(parts, parts_index + 1, abbr, ++abbr_index)) {
          return true;
        }
      } else {
        return false;
      }
    }

    return false;
  }
}

Python算法源码

# 输入获取
names = input().split(",")
abbr = input()


# 通过递归实现人名各部分和缩写的匹配
def recursive(parts, parts_index, abbr_index):
    """
    :param parts: 人名组成
    :param parts_index: 人名被匹配的组成部分的索引位置
    :param abbr_index: 缩写被匹配的字符的索引位置
    :return: 当前人名name是否匹配对应缩写abbr
    """
    if abbr_index >= len(abbr):
        # 如果缩写被匹配完,且人名组成也匹配到最后一个,则说明当前人名可以匹配对应缩写
        return parts_index >= len(parts)

    # 如果缩写尚未匹配完,但是人名组成已经匹配完,则说明当前人名无法匹配对应缩写
    if parts_index >= len(parts):
        return False

    part_name = parts[parts_index]

    for j in range(len(part_name)):
        # 如果当前人名组成部分part_name的第 j 个字符 可以 匹配 缩写abbr的第 abbr_index个字符
        if abbr_index < len(abbr) and part_name[j] == abbr[abbr_index]:
            # 为了保证part_name匹配不回退,此时我们将缩写abbr的第abbr_index+1个字符的匹配权优先交给人名的parts_index + 1部分
            abbr_index += 1
            if recursive(parts, parts_index + 1, abbr_index):
                return True
        else:
            return False

    return False


# 算法入口
def getResult():
    ans = []

    for name in names:
        parts = name.split()

        if len(parts) > len(abbr):
            continue

        if recursive(parts, 0, 0):
            ans.append(name)

    print(",".join(ans))


# 算法调用
getResult()

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?