通过回溯分割字符串

2023-12-23

我正在尝试编写一个代码,将无空格的字符串分割成有意义的单词,但是当我给出像“arealways”这样的句子时,它返回 ['a', 'real', 'ways'] 而我想要的是 ['are', '总是']我的字典包含所有这些词。我怎样才能编写一个不断回溯直到找到最佳匹配的代码?

返回“a”、“real”、“ways”的代码:

分割器.java:

public class splitter {

    HashMap<String, String> map = new HashMap<>();
    Trie dict;

    public splitter(Trie t) {
        dict = t;
    }

    public String split(String test) {
        if (dict.contains(test)) {
            return (test);
        } else if (map.containsKey(test)) {
            return (map.get(test));
        } else {
            for (int i = 0; i < test.length(); i++) {
                String pre = test.substring(0, i);
                if (dict.contains(pre)) {
                    String end = test.substring(i);
                    String fixedEnd = split(end);
                        if(fixedEnd != null){
                            map.put(test, pre + " " + fixedEnd);
                            return pre + " " + fixedEnd;
                        }else {
                        }
                    
                }
            }

        }
        map.put(test,null);
        return null;
    }
} 

特里.java:

public class Trie {
    public static class TrieNode {
        private HashMap<Character, TrieNode> charMap = new HashMap<>();
        public char c;
        public boolean endOWord;
        public void insert(String s){
        }
        public boolean contains(String s){
            return true;
        }
    }
    public TrieNode root;
    
    public Trie() {
        root = new TrieNode();
    }
    
    public void insert(String s){
        TrieNode p = root;
        for(char c : s.toCharArray()) {
            if(! p.charMap.containsKey(c)) {
                TrieNode node = new TrieNode();
                node.c = c;
                p.charMap.put(c, node);
            }
            p = p.charMap.get(c);
        }
        p.endOWord = true;
    }
    public boolean contains(String s){
        TrieNode p = root;
        for(char c : s.toCharArray()) {
            if(!p.charMap.containsKey(c)) {
                return false;
            }
            p = p.charMap.get(c);
        }
        return p.endOWord;
    }
    public void insertDictionary(String filename) throws FileNotFoundException{
        File file = new File(filename);
        Scanner sc = new Scanner(file);
        while(sc.hasNextLine())
            insert(sc.nextLine());
    }
    

    public void insertDictionary(File file) throws FileNotFoundException{
        Scanner sc = new Scanner(file);
        while(sc.hasNextLine())
            insert(sc.nextLine());
    }
} 

分词器类:

public class WordSplitter {

    public static void main(String[] args) throws FileNotFoundException {
            
           String test = "arealways";
           String myFile = "/Users/abc/Desktop/dictionary.txt";
           Trie dict = new Trie();
           dict.insertDictionary(myFile);
          splitter sp = new splitter(dict);
          test = sp.split(test);
          
          if(test != null)
          System.out.println(test);
          else
          System.out.println("No Splitting Found.");            
           
    }

        } 

使用OPsplit方法及实施Trie在发现Java 中的 Trie 数据结构 https://www.baeldung.com/trie-javaBaeldung的文章,我能够得到以下结果:

realways=real ways
arealways=a real ways

但是,如果我从字典中删除单词“real”或“a”,我会得到以下结果:

realways=null
arealways=are always

这是我用来获得这些结果的完整代码:

public class Splitter {

    private static Map<String, String> map = new HashMap<>();
    private Trie dict;
    
    public Splitter(Trie t) {
        dict = t;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<String> words = List.of("a", "always", "are", "area", "r", "way", "ways"); // The order of these words does not seem to impact the final result
        String test = "arealways";

        Trie t = new Trie();
        for (String word : words) {
            t.insert(word);
        }
        System.out.println(t);
        Splitter splitter = new Splitter(t);
        splitter.split(test);
        map.entrySet().forEach(System.out::println);
    }

    public String split(String test) {
        if (dict.find(test)) {
            return (test);
        } else if (map.containsKey(test)) {
            return (map.get(test));
        } else {
            for (int i = 0; i < test.length(); i++) {
                String pre = test.substring(0, i);
                if (dict.find(pre)) {
                    String end = test.substring(i);
                    String fixedEnd = split(end);
                    if (fixedEnd != null) {
                        map.put(test, pre + " " + fixedEnd);
                        return pre + " " + fixedEnd;
                    } else {
                    }

                }
            }

        }
        map.put(test, null);
        return null;
    }

    public static class Trie {
        private TrieNode root = new TrieNode();

        public boolean find(String word) {
            TrieNode current = root;
            for (int i = 0; i < word.length(); i++) {
                char ch = word.charAt(i);
                TrieNode node = current.getChildren().get(ch);
                if (node == null) {
                    return false;
                }
                current = node;
            }
            return current.isEndOfWord();
        }

        public void insert(String word) {
            TrieNode current = root;
            for (char l : word.toCharArray()) {
                current = current.getChildren().computeIfAbsent(l, c -> new TrieNode());
            }
            current.setEndOfWord(true);
        }
        
        @Override
        public String toString() {
            return toString(root);
        }

        /**
         * @param root2
         * @return
         */
        private String toString(TrieNode node) {
            return node.toString();
        }

        public static class TrieNode {
            private Map<Character, TrieNode> children = new HashMap<>() ;
            private String contents;
            private boolean endOfWord;

            public Map<Character, TrieNode> getChildren() {
                return children;
            }

            public void setEndOfWord(boolean endOfWord) {
                this.endOfWord = endOfWord;
            }

            public boolean isEndOfWord() {
                return endOfWord;
            }
            
            @Override
            public String toString() {
                StringBuilder sbuff = new StringBuilder();
                if (isLeaf()) {
                    return sbuff.toString();
                }
                children.entrySet().forEach(entry -> {
                    sbuff.append(entry.getKey() + "\n");
                });
                sbuff.append(" ");
                return children.toString();
            }
            
            private boolean isLeaf() {
                return children.isEmpty();
            }
        }
        
        public void delete(String word) {
            delete(root, word, 0);
        }

        private boolean delete(TrieNode current, String word, int index) {
            if (index == word.length()) {
                if (!current.isEndOfWord()) {
                    return false;
                }
                current.setEndOfWord(false);
                return current.getChildren().isEmpty();
            }
            char ch = word.charAt(index);
            TrieNode node = current.getChildren().get(ch);
            if (node == null) {
                return false;
            }
            
            boolean shouldDeleteCurrentNode = delete(node, word, index + 1) && !node.isEndOfWord();

            if (shouldDeleteCurrentNode) {
                current.getChildren().remove(ch);
                return current.getChildren().isEmpty();
            }
            return false;
        }
    }
}

我通过添加一个改进了原始代码toString()方法到Trie and TrieNode。现在,当我打印出Trie对象“t”,我得到以下结果:

{a={r={e={a=}}, l={w={a={y={s=}}}}}, w={a={y={s=}}}}

我的结论是OP的TrieNode实施不正确。方式Trie已构建,给定输入的字符串值,OP 描述的行为似乎是正确的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过回溯分割字符串 的相关文章

  • (更好的方法)使用 Eclipse 和 XText 获取项目中的文件

    我正在编写一个 XText 编辑器 并进行一些语义突出显示 我正在解析的部分语言引用了文件 这些文件应该存在于项目中 我想根据这些文件是否位于正确的位置来突出显示 目前 我有一个非常丑陋的解决方案 但我确信有更好的方法 public voi
  • string.split("(?!^)") 解释

    我正在尝试将字符串的字符拆分为字符串数组 我找到了解决方案here https stackoverflow com questions 5235401 split string into array of character strings
  • Java中如何合并两个数组?

    它不是连接而是合并两个数组 使它们成为名称值对的数组 firstarray a aa aaa secondarray b bb bbb result a b aa bb aaa bbb 最好的方法是什么 in Java public sta
  • Java:等于和==

    让我们看看我们有 2 个对用户定义类实例的引用 即 Java 中的 a 和 b 会不会有一种情况 a b 但 a equals b 返回 false 当然 实施 equals 完全取决于班级 所以我可以写 class Foo public
  • Java:将二维字符串数组打印为右对齐表格

    是什么best打印a的单元格的方法String 数组作为右对齐表 例如 输入 x xxx yyy y zz zz 应该产生输出 x xxx yyy y zz zz 这似乎是一个should能够完成使用java util Formatter
  • 如何对 jar 文件资源使用 File.separator?

    我正在尝试读取位于 jar 文件中的属性文件 我想使用 File separator 因为应用程序将在多个平台上运行 我正在构建路径如下 jarFilePath jar file jarFile getAbsolutePath jarPro
  • Android Studio:如果设置项目的背景颜色,ListView OnClick 动画将不起作用

    在我的项目中 我在 ListView 内设置了项目 由插入 ConstraintLayout 中的多个元素组成 的背景颜色 但如果背景颜色不是至少一点透明 则单击和长按的默认动画会消失 事实上 随着透明度的降低 点击元素的效果越来越不明显
  • 参考接口创建对象

    引用变量可以声明为类类型或接口类型 如果变量声明为接口类型 则它可以引用实现该接口的任何类的任何对象 根据上面的说法我做了一个理解上的代码 正如上面所说声明为接口类型 它可以引用实现该接口的任何类的任何对象 但在我的代码中显示display
  • Java:从 ScriptEngine javascript 返回一个对象

    我正在尝试使用 Java 来评估 javascript脚本引擎 https docs oracle com javase 7 docs api javax script ScriptEngine html班级 这是我正在尝试做的事情的一个简
  • 无法删除临时文件夹(有时)

    当我启动应用程序时 我创建一个临时文件夹 public static File createTempDir String name throws IOException File tempDir File createTempFile na
  • Java:如果数组大小未知,如何初始化?

    我要求用户输入 1 到 100 之间的一些数字并将它们分配到一个数组中 数组大小未初始化 因为它取决于用户输入数字的次数 我应该如何分配数组长度 如果用户输入 5 6 7 8 9 5 个数字 则 int list becomes int l
  • 覆盖Java中的属性[重复]

    这个问题在这里已经有答案了 在 Java 中 我最近有几个项目 我使用了这样的设计模式 public abstract class A public abstract int getProperty public class B exten
  • 有没有办法删除 JShell 中的导入?

    我正在发现 JShell 并且发现默认添加的导入 jshell gt imports import java io import java math import java net import java nio file import j
  • 为什么 CompletableFuture 的 thenAccept() 不在主线程上运行

    我在 CompletableFuture 的 SupplyAsync 中处理长时间运行的操作 并将结果放入 thenAccept 中 有时 thenAccept 在主线程上执行 但有时它在工作线程上运行 但我只想在主线程上运行 thenAc
  • Java 9:AES-GCM 性能

    我进行了一个简单的测试来测量AES GCM https en wikipedia org wiki Galois Counter Mode表现在Java 9 通过在循环中加密字节缓冲区 结果有些令人困惑 本机 硬件 加速似乎有效 但并非总是
  • Zookeeper 未启动,nohup 错误

    我已经下载了zookeeper 3 4 5 tar gz 解压后我将conf zoo cfg写为 tickTime 2000 dataDir var zookeeper clientPort 2181 现在我尝试通过 bin zkServe
  • Spring Data MongoDB 和批量更新

    我正在使用 Spring Data MongoDB 并且想要执行批量更新 就像此处描述的那样 http docs mongodb org manual reference method Bulk find update Bulk find
  • 在edittext android中插入imageview

    我想将 imageview 放在 edittext 中 可能吗 我检查了 evernote 应用程序 它能够将照片放在编辑文本部分 我想让我的应用程序完全相同 我如何才能将从图库中选择的图像视图放入编辑文本中 我首先尝试将 imagevie
  • 如何在 tomcat 上部署 Java Web 应用程序 (.war)?

    我有一个 warJava Web 应用程序的文件 现在我想将它上传到我的 ftp 服务器 以便我可以执行它 我应该执行哪些步骤来运行它 webapp的上下文路径是 mywebapp Edit 实际上 我的 ftp 服务器名称是ftp bil
  • 为什么我们不能在函数式接口中重载抽象方法? (爪哇)

    所以我熟悉java中的函数式接口 以及它们与lambda表达式的使用 一个函数式接口只能包含一个抽象方法 当从 lambda 表达式使用这一孤独方法时 您不需要指定其名称 因为接口中只有一个抽象方法 编译器知道这就是您正在引用的方法 Exa

随机推荐

  • HTML5 视频的图像占位符备用

    我使用以下代码在页面上实现 HTML5 视频
  • .NET System.Diagnostics.Stopwatch 问题(返回值太低)

    在我的计算机上 秒表返回的值太低 例如 当我指定时为 200 毫秒Thread Sleep 1000 该程序应该等待 1 秒 我也测试过ManualResetEvent WaitOne 1000 并得到相同的结果 框架 2 0 和 3 0
  • SQL 中的排除语句

    如何使用SQL语句从SQL数据库中排除数据 我的情况是 我有一个用户登录到他们的个人资料页面 他们可以在其中与人交友 我想显示在 SQL 数据库中找到的除他们自己之外的所有用户 也许只是 SELECT FROM Users WHERE Us
  • 如何创建一个迭代器来生成项目,其中没有项目的单个字符在 python 中表示超过 n 次?

    我创建了一个脚本 它使用以下代码来迭代 sCharacters 字符串中的所有字符组合 sCharacters abcdefghijklmnopqrstuvwxyz0123456789 iKeyLength len sCharacters
  • 如果 PostgreSQL 上不存在如何添加列?

    问题很简单 如何添加列x到餐桌y 但仅当x列不存在 我找到了唯一的解决方案here https stackoverflow com questions 9991043 how can i test if a column exists in
  • nginx代理通过Node,SSL?

    我的 nginx 服务器实际上是用一个简单的方法代理我的节点后端 监听端口 3000 location api proxy pass http upstream 1 其中upstream 1是我在nginx conf中定义的节点集群 在端口
  • 什么是跟踪分支?

    有人可以解释一下适用于 git 的 跟踪分支 吗 这是来自的定义git scm com https git scm com book en v2 Git Branching Remote Branches Git 中的 跟踪分支 是本地分支
  • 继承:选择继承哪些基类方法[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我有课Base并想写一个类Derive它仅继承了部分成员函数Base 有什么方便的方法可以做到这一点吗 例如 class Base void
  • 在 C# 中访问简单的布尔标志时,是否需要锁定或标记为易失性?

    假设您有一个在后台线程上运行的简单操作 您希望提供一种方法来取消此操作 因此您创建一个布尔标志 并从取消按钮的单击事件处理程序将其设置为 true private bool cancelled private void CancelButt
  • 如何将 Material UI 中的组件居中并使其具有响应能力?

    我不太了解 Material UI 网格系统 如果我想使用表单组件进行登录 在所有设备 移动设备和桌面设备 上将其置于屏幕中央的最简单方法是什么 因为您将在登录页面上使用它 这是我在使用 Material UI 的登录页面中使用的代码 材质
  • Pyspark - 多列聚合

    我有如下数据 文件名 babynames csv year name percent sex 1880 John 0 081541 boy 1880 William 0 080511 boy 1880 James 0 050057 boy
  • 如何使用wait\notify处理器?

    我正在运行 nifi 实例 1 2 0 我只是尝试使用 Wait Notify 处理器并参考以下内容http ijokarumawak github io nifi 2017 02 02 nifi notify batch why merg
  • Go符文类型解释

    我在 Go 中找到了符文类型 并且有一个简单的问题但值得解释一下 我发现它是int32的别名 目的是区分数字和字符值 http golang org pkg builtin rune http golang org pkg builtin
  • 如何使用 Moq 模拟会话对象集合

    我在用shanselmann 的 MvcMockHelper http www hanselman com blog ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers aspx我正在使用 Moq 来模拟
  • Mysql 使用Where 进行选择,如果where 条件不存在则默认

    我有表 Product 和 ProductDetails 在 ProductDetails 中 我有包含多种语言的产品描述的行 按 lang 列区分 并非每个产品都有每种语言的描述 如何进行选择以选择指定语言的描述 通过Where prod
  • 如何根据用户输入的值创建验证范围?

    我想在单元格 A1 中创建一个验证范围 此验证允许用户输入从 1 到 x 的值 而 x 指的是用户在 B1 中输入的值 例如 如果用户在 B1 中输入值100 那么我们只能在单元格 A1 中输入1到100 我想知道如何在 C 中做到这一点
  • 访问 Angular Material 表中的输入字段

    几天来我一直在尝试从角度材质表内的输入字段获取数据 我基本上是用来自 API 的值填充表格 但是每当我们没有获得任何日期时 在我的情况下 课程没有设置预定日期 我会插入一个文本框 其中应显示该值这样用户就可以为该特定课程设置日期 Like
  • Orange Hrm 3.1-向选项卡添加新的菜单标题

    我是 symfony 框架的新手 我使用的是 Orangehrm 3 1 1 我在第二级选项卡中添加了一个新的菜单标题 但我不知道如何导航到特定的 href 链接 请帮我完成步骤 这是我通过数据库添加菜单项的方法 要在 Orangehrm
  • 如何在 Android CalendarView 上仅显示特定月份?

    我想在 CardView 上显示特定月份without下一个和上一个箭头用于导航日历 如果我想显示 2010 年 2 月 用户必须只能看到 2010 年 2 月 他们无法查看下个月或上个月 我跟着this https stackoverfl
  • 通过回溯分割字符串

    我正在尝试编写一个代码 将无空格的字符串分割成有意义的单词 但是当我给出像 arealways 这样的句子时 它返回 a real ways 而我想要的是 are 总是 我的字典包含所有这些词 我怎样才能编写一个不断回溯直到找到最佳匹配的代