Day05【动态规划实现字符串所有切分集】

目标

给定已知字符串和相关的词表集合,实现该字符串的所有切分方式。

待切分字符串

#待切分文本
sentence = "经常有意见分歧"

对应的词表

#词典;每个词后方存储的是其词频,词频仅为示例,不会用到,也可自行修改
Dict = {"经常":0.1,
        "经":0.05,
        "有":0.1,
        "常":0.001,
        "有意见":0.1,
        "歧":0.001,
        "意见":0.2,
        "分歧":0.2,
        "见":0.05,
        "意":0.05,
        "见分歧":0.05,
        "分":0.1}

要求切分结果

#目标输出;顺序不重要
target = [
    ['经常', '有意见', '分歧'],
    ['经常', '有意见', '分', '歧'],
    ['经常', '有', '意见', '分歧'],
    ['经常', '有', '意见', '分', '歧'],
    ['经常', '有', '意', '见分歧'],
    ['经常', '有', '意', '见', '分歧'],
    ['经常', '有', '意', '见', '分', '歧'],
    ['经', '常', '有意见', '分歧'],
    ['经', '常', '有意见', '分', '歧'],
    ['经', '常', '有', '意见', '分歧'],
    ['经', '常', '有', '意见', '分', '歧'],
    ['经', '常', '有', '意', '见分歧'],
    ['经', '常', '有', '意', '见', '分歧'],
    ['经', '常', '有', '意', '见', '分', '歧']
]

思路

实现的过程主要是按照动态规划思想做的。主要思路如下:

"""
# 动态规划(DP)是解决字符串全切分问题的有效方法,其核心思想是将问题分解为子问题,并存储子问题的解以避免重复计算。以下是详细思路与实现步骤:
# 1. 问题定义
# 输入:
# 一个字符串 sentence 和一个词典 Dict(包含所有可能的词)。
# 目标:
# 输出所有可能的切分方式,使得每个切分结果中的词都存在于词典中。
# 2. 动态规划思路
# (1) 子问题定义
# 定义 dp[i] 为从位置 i 到字符串末尾的所有可能切分方式。
# 最终目标:求 dp,即从字符串开头到末尾的所有切分方式。
# (2) 状态转移方程
# 从位置 i 开始,尝试所有可能的词 word = sentence[i:j],其中 j 的范围为 [i+1, min(i+max_len, n)](max_len 为词典中最长词的长度)。
# 若 word 存在于词典中,则将 word 与 dp[j] 的所有切分方式合并,作为 dp[i] 的一部分。
# 状态转移方程:
# dp[i] = ⋃ { [word] + seg | seg ∈ dp[j] }
# 其中 j = i + len(word)。
# (3) 初始化
# dp[n] = [[]]:表示从字符串末尾到末尾的切分方式为空列表(即空字符串的切分方式)。
# (4) 计算顺序
# 从右向左计算 dp[i],因为 dp[i] 依赖于 dp[j](j > i)。
# 3. 实现步骤
# (1) 预处理
# 提取词典中的词,并计算最长词长度 max_len。
# 将词典存储为集合(set),以提高查询效率。
# (2) 动态规划表构建
# 初始化 dp 表,大小为 n+1,其中 n 为字符串长度。
# 从右向左遍历字符串,填充 dp[i]。
# (3) 结果提取
# dp 即为所有可能的切分方式。
"""

实现

def all_cut(sentence, Dict):
    # 提取词典中的词并计算最大词长
    vocab = set(Dict.keys())
    max_len = max(len(word) for word in vocab) if vocab else 0 # max_len = 3
    n = len(sentence) # n=7

    # 初始化动态规划表:dp[i] 表示从位置i到句尾的所有切分方式
    dp = [[] for _ in range(n + 1)] #8个空列表
    dp[-1] = [[]]  # 空字符串的切分方式为空列表

    # 从右向左填充dp表
    for i in range(n - 1, -1, -1): # i=6,5,4,3,2,1,0
        max_j = min(i + max_len, n)  # 避免越界 max_j=min((9,8,7,6,5,4,3),7)=(7,7,7,6,5,4,3)
        for j in range(i + 1, max_j + 1): #word从末尾往前开始取词
            word = sentence[i:j]
            if word in vocab:
                # 合并当前词与后续切分结果
                for rest in dp[j]:
                    dp[i].append([word] + rest)
    return dp[0]

测试结果

if __name__=="__main__":
    res = all_cut(sentence,Dict)
    for seg in res:
        print(seg)

运行结果:
在这里插入图片描述

你可以使用 Python 的 `split()` 方法将字符串根据空格切分为列表。这个方法会自动按空白字符(包括空格、多个连续空格、`\t`、`\n` 等)进行分割,并且**忽略空字符串**(即不会返回多余的空元素),非常适合处理已经清洗过的文本。 --- ### ✅ 解决方案:根据空格切分为列表 ```python def split_string_by_whitespace(text): return text.split() # 示例 cleaned_text = "It's a beautiful day Even with new lines and symbols" word_list = split_string_by_whitespace(cleaned_text) print(word_list) ``` #### 输出: ```python ["It's", 'a', 'beautiful', 'day', 'Even', 'with', 'new', 'lines', 'and', 'symbols'] ``` --- ### 🔍 代码解释: - `str.split()`:不带参数时,默认以**任意长度的空白字符**为分隔符进行切割。 - 即使有多个连续空格(如 `"hello world"`),也会被当作一个分隔符处理,不会产生空字符串。 - 这是推荐的方式,比 `split(' ')` 更安、更健壮。 > ❌ 不推荐写法:`text.split(' ')` > 原因:只能按单个空格切分,遇到两个以上空格会产生 `''` 空字符串#### 错误示例: ```python "hello world".split(' ') # 结果: ['hello', '', '', '', 'world'] → 有问题! ``` #### 正确做法(推荐): ```python "hello world".split() # 结果: ['hello', 'world'] → 正确! ``` --- ### 🧩 完整流程示例(清洗 + 切分) ```python import re def clean_and_split(text): # 第一步:去除所有非法字符(只保留字母、数字、空格、单引号) cleaned = re.sub(r"[^a-zA-Z0-9 ']", ' ', text) # 第二步:压缩多余空白并去除首尾空格 cleaned = re.sub(r'\s+', ' ', cleaned).strip() # 第三步:按空格切分为单词列表 return cleaned.split() # 测试 text = "Hello, World!!! It's a great day...\nLet's code together." result = clean_and_split(text) print(result) ``` #### 输出: ```python ['Hello', 'World', "It's", 'a', 'great', 'day', "Let's", 'code', 'together'] ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值