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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

#1117. 编码 ( 字典树版 ) 题解分析

發布時間:2024/4/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 #1117. 编码 ( 字典树版 ) 题解分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【問題描述】

我們準備根據一份文本編碼表對一篇文本進行壓縮。編碼表的每一項包含兩個部分:要編碼的字符串和對應的編碼。編碼是二進制的01串,用來替代文本中相應的字符串以實現壓縮編碼的目的。這些01串不一定是等長的。文本壓縮所要考慮的問題是對給定的文本和編碼表,求出能令整個文本的編碼最短的二進制串的長度。例如文本:abcdef
編碼表
a | abc | abcd |bcd|def|ef
01 | 0 | 1011 |1 |10 |11
下面有3種不同的方式進行編碼:
方式1:長度為5
a bcd ef
01 1 11
方式2:長度為3
abc def
0 10
方式3:長度為6
abcd ef
1011 11
很明顯,方式2長度最短,你的任務是找出編碼后文本的最短長度,若不能進行編碼,則輸出0.

【輸入格式】

輸入可能包含多個文本壓縮問題。
第一行是一個整數n,表示有n個文本壓縮問題。(n≤10)
每個文本壓縮問題的描述第一行是要壓縮的文本(不超過210個字符),接下來是編碼表,每項一行,不超過100項,只包含小寫字母,外側有小括號。

【輸出格式】

對應每個文本壓縮問題,每行輸出一個最小長度。

【輸入輸出樣例】

輸入樣例:

2
abcdef
(a,01)
(abc,0)
(abcd,1011)
(bcd,1)
(def,10)
(ef,11)
aa
(a,1)
(ab,10)

輸出樣例:

3
2


分割線君又來調皮了 _ (:з」∠)_


賽后和老師討論了一下這道 t ,發現雖說是有點麻煩,但是也不是很坑[ 遠沒有t1坑 _ ( :з」∠) _ ] , 如果用字典樹優化的話(其實不優化也能A過去,而且優不優化都是0ms,可以說數據水么?)可以降降時間復雜度,但是我又測了一下效率之后發現可能這么做絲毫沒有優化時間復雜度(原因:原題目中的編碼表項數太小+原數據太水),如果說編碼表項數的上線是一萬(1e4)的話那么用字典樹做優化很明顯…不然隨隨便便枚舉編碼表然后加個dp這道題也能水過去[PS: 測試點只有5個]
但是字典樹貌似也有個缺陷就是要開較大的數組(這道題在數據水的情況下我輕松就能在字典樹210個節點的情況下A了,還是數據水…),最最最最關鍵的就是要開多大的數組還很難算,本題數據賤的話貌似要2X1e4個節點的樣子(最壞情況),如上所說如果說編碼表項數是1萬的話就是2X1e6的樣子.(所以說這題數據真心水,210個節點也就這么劃過去了)

然后這題我就A了20。。。TAT 所以第一個程序的源代碼我就不放了 (還有一個原因就是我懶)_ (:з」∠)_

那么這道題既然說了字典樹就用字典樹講吧,順便讓童鞋們(也和我一起)科普科普字典樹這玩意兒。另外,本篇blog不會詳細講字典樹的內容,所以請童鞋們自行百度。


然后我就先簡要概括一下字典樹這(辣雞)玩意兒吧:

Trie樹,又稱字典樹,單詞查找樹或者前綴樹,是一種用于快速檢索的多叉樹結構,如英文字母的字典樹是一個26叉樹,數字的字典樹是一個10叉樹。與二叉查找樹不同,Trie樹的鍵不是直接保存對應的字符串,而根節點對應空字符串。一般情況下,不是所有的節點都有對應的值,只有葉子節點和部分內部節點所對應的鍵才有相關的值。它的優點是:利用字符串的公共前綴來減少查詢時間,最大限度地減少無謂的字符串比較,查詢效率比哈希樹高。搜索字典項目的方法為:1. 從根結點開始一次搜索;2. 取得要查找關鍵詞的第一個字母,并根據該字母選擇對應的子樹并轉到該子樹繼續進行檢索;3. 在相應的子樹上,取得要查找關鍵詞的第二個字母,并進一步選擇對應的子樹進行檢索。4. 迭代過程……(我也搞不懂是神馬玩意兒,反正在這里應該就是下標一類的玩意兒了)5. 在某個結點處,關鍵詞的所有字母已被取出,則讀取附在該結點上的信息,即完成查找。

順便盜個圖

emm…都是借鑒來的介紹、、、其他關于字典樹的東西這里就不贅述了,如有興趣自行百度。

好了,上代碼吧。(對了,程序里的主函數中有許多字符串的函數,如有不懂的可以去搜一下,順便當做復習)


include<bits/stdc++.h> //運用字典樹來處理查找問題 using namespace std; int n,k,h,rt; string s,p; int len,v,dp[210]; //dp[i]表示在做到i號位置時付出的最小價值 int trie[210][26]; //trie[i][j]表示在第i號節點的后繼中,有無j字母,//如果有,那么這個后繼的編號則記錄在trie[i][j]中 int val[210]; //val[i]表示在字典樹的第i號節點上有無完整字符串//如果有,那么這個字符串的價值就記錄在val[i]中 void work() {len=s.length(); //len賦值為s的(有效)長度s=" "+s; //s前加個空格方便操作for(int i=1;i<=len;++i) //從前往后做dp{rt=0; //從根節點開始查找for(int j=i;j>=1;--j)//一直往前找,按照要壓縮的文本字符串查找是否已有此字符串編碼{int x=s[j]-'a';if(!trie[rt][x]) break; //查無此字符串,則直接退出 //(找不到當前節點的話后面也不用再找下去了,相當于樹到這里已經斷了, //字符串在字典樹中已經不可能匹配了) rt=trie[rt][x]; //獲得該節點的后繼 x 字母的節點編號if(val[rt]!=0x3f3f3f3f && dp[j-1]!=0x3f3f3f3f)dp[i]=min(dp[i] , dp[j-1]+val[rt]); //取最小值}}cout<< (dp[len]==0x3f3f3f3f ? 0 : dp[len]) <<endl; //直接輸出dp[len] }int main() {ios::sync_with_stdio(false); //輸入輸出流的優化,你懂的 (o^.^o)cin>>n>>s; while(n--) {k=0; h=0;memset(trie , 0 , sizeof(trie));memset(val , 0x3f , sizeof(val));memset(dp , 0x3f , sizeof(dp)); dp[0]=0; //將整個dp數組賦值inf之后,//要把dp[0]賦為0,作為dp的基礎while(cin>>p && p[0]=='('){ //這里就是對讀入的數據是否是編碼表項len=p.find(',')-p.find('(')-1; // 運用字符串函數得到p的長度 和 價值v=p.find(')')-p.find(',')-1;p=p.substr(1,len); //取出真正的 編碼rt=0;for(int i=len-1;i>=0;--i)//這里從后往前存點,因為等會兒的dp也是從后往前匹配的{int x=p[i]-'a'; //得到的x代表了26個字母之一if(!trie[rt][x]) //如果尚未有點就自己建一個點trie[rt][x]=++h;rt=trie[rt][x]; //然后rt指向當前節點的后繼 x 字母}val[rt]=min(val[rt] , v); //最終在樹的字符串底端}work();s=p; //之前讀入的非編碼表項其實是要壓縮的文本,直接賦值給s }return 0; }

ok,這就是字典樹的做法了。希望童鞋們看完后能有所收獲 QAQ

另外附上我的實驗結果(十組數據時):

編碼表項數\優化方法無優化線性枚舉區間預處理字典樹優化
10070ms40ms50ms
1000350ms90ms60ms
100003200ms570ms240ms

然后……再見 _ (:з」∠)_

轉載于:https://www.cnblogs.com/Judge/p/9383040.html

總結

以上是生活随笔為你收集整理的#1117. 编码 ( 字典树版 ) 题解分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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