[译]单词分割

本文介绍了一种判断字符串是否能被分割成字典中单词序列的方法,包括普通递归和动态规划两种实现方式,并提供了一个简单高效的Java实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接: 单词分割

给定一个字符串s和一个单词字典,确定是否可以将s分割为一个或多个字典单词的空格分隔的序列。
例如:

For example, given
s = "leetcode",
dict = ["leet", "code"].

因为"leetcode"可以分割为"leet code", 所以返回true.

  1. 普通方法
    这个问题可以用一种简单的方法来解决。讨论总是可以从这个开始。
public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
             return wordBreakHelper(s, dict, 0);
    }
 
    public boolean wordBreakHelper(String s, Set<String> dict, int start){
        if(start == s.length()) 
            return true;
 
        for(String a: dict){
            int len = a.length();
            int end = start+len;
 
            //end index should be <= string length
            if(end > s.length()) 
                continue;
 
            if(s.substring(start, start+len).equals(a))
                if(wordBreakHelper(s, dict, start+len))
                    return true;
        }
 
        return false;
    }
}

时间是O(n ^ 2)和超过了时间限制。

  1. 动态程序
    利用动态规划方法解决这个问题的关键是:
定义一个数组t[],这样t[i]= =true => 0-(i- 1)可以使用字典进行分段
初始状态t[0]= = true
public class Solution {
    public boolean wordBreak(String s, Set<String> dict) {
        boolean[] t = new boolean[s.length()+1];
        t[0] = true; //set first to be true, why?
        //Because we need initial state
 
        for(int i=0; i<s.length(); i++){
            //should continue from match position
            if(!t[i]) 
                continue;
 
            for(String a: dict){
                int len = a.length();
                int end = i + len;
                if(end > s.length())
                    continue;
 
                if(t[end]) continue;
 
                if(s.substring(i, end).equals(a)){
                    t[end] = true;
                }
            }
        }
 
        return t[s.length()];
    }
}

时间:O(字符串长度*字典大小)。

  1. Java解决方案3 -简单高效
    在方案2中, 如果字典的数据量是非常大的, 时间是非常长的.相反,我们可以解决这个问题在O(n ^ 2)时间(n是字符串的长度).
public boolean wordBreak(String s, Set<String> wordDict) {
    int[] pos = new int[s.length()+1];
 
    Arrays.fill(pos, -1);
 
    pos[0]=0;
 
    for(int i=0; i<s.length(); i++){
        if(pos[i]!=-1){
            for(int j=i+1; j<=s.length(); j++){
                String sub = s.substring(i, j);
                if(wordDict.contains(sub)){
                    pos[j]=i;
                }
            } 
        }
    }
 
    return pos[s.length()]!=-1;
}
#!/bin/bash word_file="words.txt" difficult_file="difficult.txt" wrong_file="wrong.txt" if [[ ! -f "$word_file" ]]; then touch "$word_file" fi count_words() { word_count=$(wc -l < "$word_file") echo "当前单词数量: $word_count" } add_word() { echo "请输入单词:" read word echo "请输入该单词的汉语释义:" read meaning echo "$word:$meaning" >> "$word_file" echo "单词添加成功!" } find_word() { echo "请输入要查找的单词:" read word result=$(grep -i "^$word" "$word_file") if [[ -z "$result" ]]; then echo "没有找到该单词的释义" else echo "单词释义:$result" fi } random_word() { random_line=$(shuf -n 1 "$word_file") echo "随机单词: $random_line" } review_words() { while true; do echo "复习中,请按Ctrl+C退出。" random_word sleep 2 done } delete_word() { echo "请输入要删除的单词:" read word sed -i "/$word/d" "$word_file" echo "单词已删除!" } alter_word() { echo "请输入要修改的单词:" read word echo "请输入新的释义:" read new_meaning sed -i "/^$word:/c\\$word : $new_meaning" "$word_file" echo "单词释义已修改!" } zyywrite_word() { original_ifs=$IFS IFS=":" echo "默写单词,输入正确的释义(中英)。按 Ctrl+C 随时退出。" while read -r word meaning; do echo -n "请输入 '$meaning' 的英文单词: " sleep 5 # 调整为更合理的等待时间 read -t 5 answer # 允许用户在 5 秒内输入答案 if [[ "$answer" == "$word" ]]; then echo "正确!" else echo "错误!正确答案是: $word" fi done < "$word_file" IFS=$original_ifs # 恢复原始 IFS 值 } menu() { while true; do echo echo " ***************i*************" echo " * 单词小助手 *" echo " ****************************" echo " * 操作选项: *" echo " * 1. 添加单词 *" echo " * 2. 删除单词 *" echo " * 3. 修改单词 *" echo " * 4. 查找单词释义 *" echo " * 5. 随机输出单词 *" echo " * 6. 复习生词/难词/易错词 *" echo " * 7. 单词默写(中英) *" echo " * 8. 退出 *" echo " ****************************" echo -n "请输入你的选项:" read choice case $choice in 1) add_word ;; 2) delete_word ;; 3) alter_word ;; 4) find_word ;; 5) random_word ;; 6) review_words ;; 7) zyywrite_word ;; 8) exit 0 ;; *) echo "无效选项,请重新选择。" ;; esac done } menu 修改优化代码
最新发布
06-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值