使用单词表拼接长字符串的方法数

简介: 使用单词表拼接长字符串的方法数

题目

假设所有字符都是小写字母
大字符串是str
arr是去重的单词表, 每个单词都不是空字符串且可以使用任意次.
使用arr中的单词有多少种拼接str的方式. 返回方法数.

解题思路

该题为从左到右模型

步骤

基本思路就是以i位置为开头(假设前面的位置都拼接好了),有多少种拼接方法
我们遍历从i到i位置能不能拼接
i到i+1能不能拼接
i到i+2能不能拼接
....
i到N能不能拼接

    public static int ways(String str, String[] arr) {
        HashSet<String> set = new HashSet<>();
        for (String candidate : arr) {
            set.add(candidate);
        }
        return process(str, 0, set);
    }

    // 所有的可分解字符串,都已经放在了set中
    // str[i....] 能够被set中的贴纸分解的话,返回分解的方法数
    public static int process(String str, int i, HashSet<String> set) {
        if (i == str.length()) { // 没字符串需要分解了!
            return 1;
        }
        //  i....还有字符串需要分解
        int ways = 0;
        // [i ... end] 前缀串 每一个前缀串
        for (int end = i; end < str.length(); end++) {
            String pre = str.substring(i, end + 1);// [)
            if (set.contains(pre)) {
                ways += process(str, end + 1, set);
            }
        }
        return ways;
    }
AI 代码解读

方法中只有一个可变参数,这就是一个一维动态规划表

dp[i]:
str从i出发及其后面所有的字符串被set分解有几种方法
整张表都填完,0位置返回就是最终答案
复杂度O(N^3)
因为有前缀字符串的检查

优化

使用前缀树记录set的字符串,减少前缀字符串的检查代价

这个点他往下没有走向a的路了,你以后所有的前缀串都不用查了
每次查一个前缀串有没有,它就是在前缀树移动一个格子。而且如果没有路了,你可以直接返回

代码

    public static class Node {
        public boolean end;
        public Node[] nexts;

        public Node() {
            end = false;
            nexts = new Node[26];
        }
    }

    public static int ways3(String str, String[] arr) {
        if (str == null || str.length() == 0 || arr == null || arr.length == 0) {
            return 0;
        }
        Node root = new Node();
        for (String s : arr) {
            char[] chs = s.toCharArray();
            Node node = root;
            int index = 0;
            for (int i = 0; i < chs.length; i++) {
                index = chs[i] - 'a';
                if (node.nexts[index] == null) {
                    node.nexts[index] = new Node();
                }
                node = node.nexts[index];
            }
            node.end = true;
        }
        return g(str.toCharArray(), root, 0);
    }

    // str[i...] 被分解的方法数,返回

    public static int g(char[] str, Node root, int i) {
        if (i == str.length) {
            return 1;
        }
        int ways = 0;
        Node cur = root;
        // i...end
        for (int end = i; end < str.length; end++) {
            int path = str[end] - 'a';
            if (cur.nexts[path] == null) {
                break;
            }
            cur = cur.nexts[path];
            if (cur.end) { // i...end
                ways += g(str, root, end + 1);
            }
        }
        return ways;
    }
AI 代码解读
相关文章
autojs下拉刷新
牙叔教程 简单易懂
1068 0
使用Python实现深度学习模型:智能垃圾分类与回收系统
【8月更文挑战第20天】 使用Python实现深度学习模型:智能垃圾分类与回收系统
416 1
深度学习之设备异常检测与预测性维护
基于深度学习的设备异常检测与预测性维护是一项利用深度学习技术分析设备运行数据,实时检测设备运行过程中的异常情况,并预测未来可能的故障,以便提前进行维护,防止意外停机和生产中断。
435 1
编程语言中的静态和动态类型语言
【7月更文挑战第14天】本文介绍静态与动态类型语言对比。类型检查效率是关键,一些系统可能在极端情况下慢。自动化与高效算法的研究持续进行.
123 5
编程语言中的静态和动态类型语言
【全栈小程序开发路线】手把手教你入门小程序开发,小白必看!
以下内容是结合我项目中实战经验,踩坑记录,大量时间学习小程序的积累,总结分享给大家。 学习路线包括前端基础、小程序开发框架、UI组件库、云开发、周边生态以及插件这几个纬度,学完这些,你也能全栈开发一个属于自己的产品。
834 0
Java中的Lambda表达式:简洁、灵活、高效
Lambda表达式是Java 8引入的重要特性,它为Java编程带来了更简洁、更灵活、更高效的编程方式。本文将深入探讨Lambda表达式的语法、特性以及在实际开发中的应用,帮助读者更好地理解和应用Lambda表达式。
图像嵌入(Image Embedding
机器学习中的图像嵌入(Image Embedding)是一种将图像数据转化为连续的、低维度的向量表示的方法,这些向量表示通常用于后续的机器学习任务,如分类、聚类、检索等。图像嵌入的目的是将高维度的图像数据转化为更易于处理的低维度数据,同时保留尽可能多的原始图像信息。常用的图像嵌入方法包括:
3882 3
Mysql_3 ER 和 EER 模型
学习于:b站 骆昊 jackfrued 老师的网课+黑马网课
764 0
Mysql_3 ER 和 EER 模型
王道考研操作系统同步与互斥(王道大题详解)(一)
王道考研操作系统同步与互斥(王道大题详解)(一)
390 0
王道考研操作系统同步与互斥(王道大题详解)(一)

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等