【线性 dp】B018_LC_恢复空格(分类讨论)

一、Problem

哦,不!你不小心把一个长篇文章中的空格、标点都删掉了,并且大写也弄成了小写。像句子"I reset the computer. It still didn’t boot!“已经变成了"iresetthecomputeritstilldidntboot”。在处理标点符号和大小写之前,你得先把它断成词语。当然了,你有一本厚厚的词典dictionary,不过,有些词没在词典里。假设文章用sentence表示,设计一个算法,把文章断开,要求未识别的字符最少,返回未识别的字符数。

注意:本题相对原题稍作改动,只需返回未识别的字符数

输入:
dictionary = ["looked","just","like","her","brother"]
sentence = "jesslookedjustliketimherbrother"
输出: 7
解释: 断句后为"jess looked just like tim her brother",共7个未识别字符。

提示:

0 <= len(sentence) <= 1000
dictionary中总字符数不超过 150000。
你可以认为dictionary和sentence中只包含小写字母。

二、Solution

方法一:dp

  • 定义状态
    • f [ i ] f[i] f[i] 表示子串 s [ 0 : i ] s[0:i] s[0:i] 断句后的最少未识别的字符数
  • 思考初始化:
    • f [ 0 ] = 0 f[0] = 0 f[0]=0
    • 如果子串 s [ 0 : i ] s[0:i] s[0:i] 中每一个字符都识别不了,那么 f [ i ] = i f[i] = i f[i]=i,但因为过程中可能识别到若干子串,所以,这段初始化可不写…
  • 思考状态转移方程
    • 如果第 i i i 个字符不可识别,则 f [ i ] = f [ i − 1 ] + 1 f[i] = f[i-1] + 1 f[i]=f[i1]+1
    • 如果子串 s [ j : i ] s[j:i] s[j:i] 中每一个字符都可识别,那么我不将 s [ j : i ] s[j:i] s[j:i] 这一整段字符计到识别不了的账中,则 f [ i ] = m i n ( f [ i ] , f [ j ] ) ( j < i ) f[i] = min(f[i], f[j])(j < i) f[i]=min(f[i],f[j])j<i
  • 思考输出 f [ n ] f[n] f[n]
class Solution {
public:
    int respace(vector<string>& dictionary, string s) {
    	int n = s.size();
    	vector<int> f(n+1); f[0] = 0;
    	unordered_set<string> st(dictionary.begin(), dictionary.end());

    	for (int i = 1; i <= n; i++) {
    		f[i] = f[i-1] + 1;
    		for (int j = 0; j < i; j++) {
    			if (st.count(s.substr(j, i-j))) 
    				f[i] = min(f[i], f[j]);
    		}
    	}
    	return f[n];
    }
};

复杂度分析

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3)
  • 空间复杂度: O ( n ) O(n) O(n)

你可能感兴趣的:(#,线性,dp)