Word Break II

本文介绍了一种用于将字符串分割成有效字典单词组合的算法。通过使用二维数组记录子串是否能被有效分割,结合递归搜索策略,实现了对输入字符串的有效分割。

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

题目:

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

s = "catsanddog",dict = ["cat", "cats", "and", "sand", "dog"].A solution is ["cats and dog", "cat sand dog"].

思路:

设立一个数组Br[][],在一个大循环i里面,再设置一个小循环j,数组Br每一行存储从数组0到i中的子串能否被分割,最后进行搜索。详见下面分析。

首先要理解的就是这个Br[][],建议从头理解较好。这边就是一个难点。

(1).i=x,再令j从i减小到0,其中先是判断 s[j...i]能否在提供的字符串中找到,再判断一个条件,就是(j=0||Br[j-1]不为空),j=0意思就是从头到i都在提供的字符串中,Br[j-1]不为空的意思是s[0....j-1],是能够被分解的。所以研究到现在,Br[i][]这个数组的作用就是判断s[0....i]能否被分解,且其中存放的j代表好几种分类:s[j...i]能够被找到,s[k...i]能够被找到,而巧的就是Br[j],Br[k]也是能够被分解的,在前面已经找到了。所以,最后呢,对于Br[n-1],存放了一系列数字:a,b,c,d.....,

都是代表s[a...n]能够被分解,s[b...n]能够被分解,s[c...n]能够被分解,s[d...n]能够被分解,更加巧的是,Br[a],Br[b],Br[c],Br[d]他们都是不为空的,都是能够找到分解的子串的。这一点在接下来的程序中也是用的到的。

(2).然后就是这个breakHelper函数了,非常巧妙,我现在还不知道深搜广搜,但这个程序是能够看懂的,算是一种入门了。到后期再改博客。

具体的参数不写了,浪费时间,一开始就是index=n-1的,Br[index]里面存放的第一个是从这个值到n-1能够找到,而且Br[这个值]不为空,然后函数继续递归调用,这个时候start就要减1了。因为从最后到这个值,我已经能够找到,剩下的就是找前面的啦。就是这么理解。

欢迎指正!!!


代码:

class Solution {
public:
//https://leetcode.com/problems/word-break-ii/
	void breakHelper(string &s,int index,vector<vector<int> > &Br,vector<string> &answer,vector<string> &result){
		if (index<0){
			//append()函数用来将一个字符串连接在另一个字符串的后面
			string r(answer[answer.size()-1]);
			for (int i=answer.size()-2;i>=0;i--){
				r.push_back(' ');
				r.append(answer[i]);
			}
			result.push_back(r);
			return ;
		}
		//index<0 的时候先不考虑

		//这个时候Br二维数组最后一行存放的就是能够分开的索引值,比如说4,5,8
		//应该来说,是各种各样的,可能从2能分开,4也能分开,可能0-4就是一组
		//如果这样,i=4,就说明从4-n就在数组里面
		for (int i=0;i<Br[index].size();i++){
			int start=Br[index][i];//这个就代表从start开始到最后,是完全能够找得到,都在dict里面
			answer.push_back(s.substr(start,index-start+1));
			breakHelper(s,start-1,Br,answer,result);//因为start到n都能找到,所以开始找0-start-1的
			answer.pop_back();//他这个是很多个循环,最后一次i之后全部清空,方便下次再进入			
		}
	}


	vector<string> wordBreak(string s, unordered_set<string> &dict) {
		//程序的一个意思就是,在一个大循环i里面,再设置一个小循环j
		//数组Br每一行存储从数组0到i中的子串能否被分割
		//条件就是从j到i能够在提供的所有字符串中找到,且Br[j-1]不为空---意思就是我从0到j也能够被分割,至于存放啥,不管。

		vector<string> result;

		if(s.empty()){
			result.push_back("");
			return result;
		}

		const int n=s.size();
		vector <vector <int> >Br(n,vector<int>());

		for (int i=0;i<n;i++){
			for (int j=i;j>=0;j--){
				if (dict.find(s.substr(j,i-j+1))!=dict.end()&&(j==0||!Br[j-1].empty())){
					//从j开始
					Br[i].push_back(j);
				}
			}
		}

		vector<string> answer;
		breakHelper(s,n-1,Br,answer,result);
		return result;
	}
};



### CSS `word-break` 属性详解 #### 定义与作用 `word-break` 是一个用于控制单词内断行行为的 CSS 属性。该属性定义了如何处理过长而不适合其容器宽度的文字,以及在何种情况下允许这些文字被拆分到多行显示。 #### 可选值及其效果 - **normal**: 使用默认规则来决定在哪里可以折行。通常只会在空格处或连字符上换行[^1]。 - **break-all**: 允许在任何字符间断开,即使是在非空白字符之间也会强制换行。这种设置对于包含大量不可分割长词的语言(如中文、日文)特别有用[^2]。 - **keep-all**: 防止除字典定义外的地方发生断裂;适用于不允许随意切割词语的情况,比如英文中的专有名词等[^3]. #### 实际应用案例 当页面布局中有固定大小但可能容纳不下某些较长文本内容时,可以通过调整此样式属性使溢出部分合理地分布于下一行而不是超出边界造成视觉混乱: ```html <div style="width: 200px; border: solid;"> <!-- 这里放置一段很长且无自然间隔符的日语字符串 --> </div> ``` 为了确保上述 HTML 中的内容能够在指定宽度范围内正确展示而不会破坏整体设计美感,则可以在对应的 `<style>` 或外部样式表文件中加入如下声明: ```css /* 设置 div 的 word-break 行为 */ div { word-break: break-all; } ``` 这样就可以让那些超宽却不含合法打断位置的文字也能按照预期表现出来,既不破坏原有结构又实现了良好的用户体验[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值