日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

程序员面试金典 - 面试题 17.13. 恢复空格(DP+Trie树)

發布時間:2024/7/5 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员面试金典 - 面试题 17.13. 恢复空格(DP+Trie树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1. 題目
    • 2. 解題
      • 2.1 動態規劃
      • 2.2 Trie樹

1. 題目

哦,不!你不小心把一個長篇文章中的空格、標點都刪掉了,并且大寫也弄成了小寫。
像句子"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個未識別字符。(jess tim)提示: 0 <= len(sentence) <= 1000 dictionary中總字符數不超過 150000。 你可以認為dictionary和sentence中只包含小寫字母。

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/re-space-lcci
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。

2. 解題

2.1 動態規劃

  • dp[i] 表示包含 i 字符結尾的字符串 最少的未識別字符數,初始為 i+1(全部未識別)
  • 將 [ 0, i ] 區間切分,[ 0, j-1 ],[ j, i ] ,遍歷所有的 j (j <= i)
  • 如果字典包含字符串 [ j, i ],dp[i]=min?(dp[i],dp[j?1])dp[i] = \min(dp[i], dp[j-1])dp[i]=min(dp[i],dp[j?1])
  • 如果字典不包含字符串 [ j, i ],dp[i]=min?(dp[i],dp[j?1]+i?j+1)dp[i] = \min(dp[i], dp[j-1]+i-j+1)dp[i]=min(dp[i],dp[j?1]+i?j+1)
  • 一旦 dp[i] == 0,可以終止內層循環
class Solution { public:int respace(vector<string>& dictionary, string sentence) {if(sentence.empty())return 0;int i, j, n = sentence.size();unordered_set<string> s;vector<int> dp(n,INT_MAX);for(auto& d : dictionary)s.insert(d);for(i = 0; i < n; ++i){dp[i] = i+1;if(s.count(sentence.substr(0,i+1))){dp[i] = 0;continue;}for(j = i; j > 0; --j){if(s.count(sentence.substr(j,i-j+1)))dp[i] = min(dp[i], dp[j-1]);elsedp[i] = min(dp[i], dp[j-1]+i-j+1);if(dp[i]==0)break;}}return dp[n-1];} };

1156 ms 446.1 MB

2.2 Trie樹

  • 在上面的思路下,將字典字符串反向插入trie樹
  • 內層循環可以改為向前在trie樹中查找存在的字符串最大長度,一旦不存在某個字符就不必再往前遍歷了,因為肯定不存在,可以提高效率。
class trie { public:trie* cur;trie* next[26] = {NULL};bool isEnd = false;void insert(string& s){cur = this;for(int i = s.size()-1; i >= 0; --i)//反向插入{if(cur->next[s[i]-'a'] == NULL){cur->next[s[i]-'a'] = new trie();}cur = cur->next[s[i]-'a'];}cur->isEnd = true;} };class Solution { public:int respace(vector<string>& dictionary, string sentence) {if(sentence.empty())return 0;int i, j, n = sentence.size();unordered_set<string> s;trie *t = new trie(), *cur;for(auto& d : dictionary)t->insert(d);//字典插入trie樹vector<int> dp(n,INT_MAX);for(i = 0; i < n; ++i){dp[i] = i+1;cur = t;for(j = i; j >= 0; --j)//從i處向前在trie樹中查找單詞{ if(cur->next[sentence[j]-'a'])//下一個字符存在{if(cur->next[sentence[j]-'a']->isEnd)//且是結束位置{if(j > 0)dp[i] = min(dp[i], dp[j-1]);elsedp[i] = 0;}else//不是結束位置,不匹配{if(j > 0)dp[i] = min(dp[i], dp[j-1]+i-j+1);elsedp[i] = min(dp[i], i-j+1);}}else//下一個字符不存在,可以結束了{if(j > 0)dp[i] = min(dp[i], dp[j-1]+i-j+1);elsedp[i] = min(dp[i], i-j+1);break;}if(dp[i]==0) break;cur = cur->next[sentence[j]-'a'];}}return dp[n-1];} };

120 ms 153.8 MB


我的CSDN博客地址 https://michael.blog.csdn.net/

長按或掃碼關注我的公眾號(Michael阿明),一起加油、一起學習進步!

總結

以上是生活随笔為你收集整理的程序员面试金典 - 面试题 17.13. 恢复空格(DP+Trie树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。