leetcode 1531 壓縮字串
阿新 • • 發佈:2020-07-27
題意
行程長度編碼 是一種常用的字串壓縮方法,它將連續的相同字元(重複 2 次或更多次)替換為字元和表示字元計數的數字(行程長度)。例如,用此方法壓縮字串 "aabccc" ,將 "aa" 替換為 "a2" ,"ccc" 替換為` "c3" 。因此壓縮後的字串變為 "a2bc3" 。
注意,本問題中,壓縮時沒有在單個字元後附加計數 '1' 。
給你一個字串 s 和一個整數 k 。你需要從字串 s 中刪除最多 k 個字元,以使 s 的行程長度編碼長度最小。
請你返回刪除最多 k 個字元後,s 行程長度編碼的最小長度 。
思路
dp[i][j][last][concat]表示前i個字元,刪除j個,最後一個為last,當前到最後一個字元最長相同字元個數為concat時編碼的最小長度。
每一個字元有刪除和連線兩種操作,刪除時狀態轉移為dp[i-1][j-1][last][concat]
連線時如果當前字元和last相等,需要考慮concat的個數,因為當concat從1變為2,從9變為10,從99變為100時,數目是增加1的
若連線時字元不同,重新跟新last和concat的數值
int dp[105][105][27][15]; const int maxn=0x3f3f3f3f; string s; int dfs(int idx,int k,int last,int concat) { if(k<0) return 0x3f3f3f3f; if(idx==s.size()) return 0; int&val =dp[idx][k][last][concat]; if(val!=-1) return val; int ans=maxn; //刪除 ans=min(ans,dfs(idx+1,k-1,last,concat)); //concat if(last==s[idx]-'a') { int fac=(concat == 1 || concat == 9|| concat==99) ? 1 : 0; ans=min(ans,dfs(idx+1,k,last,min(10, concat + 1))+fac); } else ans=min(ans,dfs(idx+1,k,s[idx]-'a',1)+1); return val=ans; } int getLengthOfOptimalCompression(string s, int k) { this->s=s; //特判下s=100,k=0,全部為同一字元的情形是否出現 memset(dp,-1,sizeof(dp)); return dfs(0,k,26,0); }
思路2,dp[i][j]表示前i個字元刪除j個,那麼對第i個字元有刪除和不刪除兩種;對於不刪除,我們考慮在不超過k的條件下可以走多遠
int dp[105][105]; int getLengthOfOptimalCompression(string s, int k) { int n = s.size(); memset(dp, 0x3f, sizeof(dp)); dp[0][0] = 0; for(int i = 1; i <= n; i++) { for(int j = 0; j <= k; j++) { dp[i][j + 1] = min(dp[i][j + 1], dp[i - 1][j]); int cnt = 0, del = 0; for(int l = i; l <= n; l++) { cnt += s[l - 1] == s[i - 1]; del += s[l - 1] != s[i - 1]; if(j + del <= k) dp[l][j + del] = min(dp[l][j + del], dp[i - 1][j] + 1 + (cnt >= 100 ? 3 : cnt >= 10 ? 2 : cnt >= 2 ? 1: 0)); } } } return dp[n][k]; }