Leetcode: Minimum Unique Word Abbreviation
A string such as "word" contains the following abbreviations: ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"]
Given a target string and a set of strings in a dictionary, find an abbreviation of this target string with the smallest possible length such that it does not conflict with abbreviations of the strings in the dictionary. Each number or letter in the abbreviation is considered length = 1. For example, the abbreviation "a32bc" has length = 4. Note:
In the case of multiple answers as shown in the second example below, you may return any one of them.
Assume length of target string = m, and dictionary size = n. You may assume that m ≤ 21, n ≤ 1000, and log2(n) + m ≤ 20.
Examples:
"apple", ["blade"] -> "a4" (because "5" or "4e" conflicts with "blade") "apple", ["plain", "amber", "blade"] -> "1p3" (other valid answers include "ap3", "a3e", "2p2", "3le", "3l1").
Refer to https://discuss.leetcode.com/topic/61799/java-bit-mask-dfs-with-pruning
bit mask refer to http://bookshadow.com/weblog/2016/10/02/leetcode-minimum-unique-word-abbreviation/
1. The key idea of my solution is to preprocess the dictionary to transfer all the words to bit sequences (int):
比如apple 和 amper 字母相同设1,不同设0,所以得到10100
又比如target='apple',word='amble',则word的bitmask为10011
在这个过程中ignore与target长度不一样的,得到每个字典里面的bitmask,下面称呼它为mask,所以mask里为1的位表示与target字母相同
a p p l e
a m b l e
1 0 0 1 1
2. 开始缩写target单词,只不过我们不直接缩写成十进制数,而是先缩写成二进制,1表示保留字母,0表示替换为数字。下面称呼这个当前的缩写结果为curResult, 因为curResult由target缩写而来,所以curResult里为1的位与target字母相同
例如单词manipulation的缩写m2ip6n可以转化为100110000001
m a n i p u l a t i o n
m 2 i p 6 n
1 0 0 1 1 0 0 0 0 0 0 1
3. mask里为1的位表示与target字母相同, 同时curResult里为1的位也与target字母相同, 如果
curResult & mask == curResult,
则说明curResult里为1的位子上,mask也一定是1,那么curResult也一定是mask所对应的那个string的一个缩写,所以这里conflict出现了,所以这个curResult要被skip掉
4. 在所有没有conflict的curResult里面,找到长度最短的一个,如何找到长度最短,可以在recursion里面维护一个当前curResult长度大小的变量,同时有一个变量保存最小长度用以更新
5. 最后将长度最短那个curResult(它目前只是一个二进制缩写),复原成十进制缩写
这是我做过最难的Bitmask的题了
public class Solution {
private int minLen;
private int result;
public String minAbbreviation(String target, String[] dictionary) {
// only keep words whose length == target in new dict, then compute their bit masks
Set<Integer> maskSet = new HashSet<>();
for(String s: dictionary){
if(target.length() == s.length()){
maskSet.add(getBitMask(s,target));
}
}
// dfs with pruning
minLen = target.length()+1;
result = -1;
dfs(target,maskSet,0,0,0);
if(minLen > target.length()){
return "";
}
// convert result to word
int zeroCnt = 0;
String res = "";
for (int i = target.length()-1; i>=0; i--) {
//遇到0要累加连续零个数,遇到1填原char
int digit = (result & 1);
if(digit == 0){
++zeroCnt;
} else {
if(zeroCnt > 0){
res = zeroCnt + res;
zeroCnt =0;
}
res = target.charAt(i) + res;
}
result >>= 1;
}
if(zeroCnt > 0) res = zeroCnt + res;
return res;
}
/**
*
* @param target
* @param maskSet masks of words in dict
* @param start idx at target
* @param curLen current abbr's length
*/
private void dfs(String target,Set<Integer> maskSet,int start,int curLen,int curResult){
// pruning, no need to continue, already not min length
if(curLen >= minLen) return;
if(start == target.length()){
// check whether curResult mask conflicts with words in dict
for(int mask:maskSet){
/**
* 单词manipulation的缩写m2ip6n可以转化为100110000001
* m a n i p u l a t i o n
m 2 i p 6 n
1 0 0 1 1 0 0 0 0 0 0 1
* 0代表随意不care,如果这个mask和dict中某个mask的所有1重合代表在意的位置完全相同,
* 说明这个mask和dict中那个词冲突
* 我们要找的是不冲突的mask
*/
if((curResult & mask) == curResult){
return; // conflict
}
}
// no conflict happens, can use
if(minLen > curLen){
minLen = curLen;
result = curResult;
}
return;
}
// case 1: replace chars from start in target with number
for (int i = start; i < target.length(); i++) {
//被replace掉的char位置由0代替所以是curResult<<(i+1-start),没replace掉的这里不管,我们只管到i,之后的由backtrack内决定
//注意:不允许word => w11d这种用数字代替但含义不同
if(curLen == 0 || (curResult &1) == 1){
//后者即上一次是保留了字母
dfs(target,maskSet,i+1,curLen+1,curResult<<(i+1-start));
}
}
// case 2: no replace from start (curResult << 1)+1代表新的这位保留了char,所以是加一
dfs(target,maskSet,start+1,curLen+1,(curResult << 1)+1);
}
// 比如apple 和 amper 字母相同设1,不同设0,所以得到10100
private int getBitMask(String s1,String s2){
int mask = 0;
for (int i = 0; i < s1.length(); i++) {
mask <<= 1;
if(s1.charAt(i) == s2.charAt(i)){
mask += 1;
}
}
return mask;
}
}
Leetcode: Minimum Unique Word Abbreviation的更多相关文章
- [LeetCode] Minimum Unique Word Abbreviation 最短的独一无二的单词缩写
A string such as "word" contains the following abbreviations: ["word", "1or ...
- [LeetCode] 288.Unique Word Abbreviation 独特的单词缩写
An abbreviation of a word follows the form <first letter><number><last letter>. Be ...
- 411. Minimum Unique Word Abbreviation
A string such as "word" contains the following abbreviations: ["word", "1or ...
- [Locked] Unique Word Abbreviation
Unique Word Abbreviation An abbreviation of a word follows the form <first letter><number&g ...
- Leetcode Unique Word Abbreviation
An abbreviation of a word follows the form <first letter><number><last letter>. Be ...
- 288. Unique Word Abbreviation
题目: An abbreviation of a word follows the form <first letter><number><last letter> ...
- Unique Word Abbreviation
An abbreviation of a word follows the form <first letter><number><last letter>. Be ...
- [LeetCode] Unique Word Abbreviation 独特的单词缩写
An abbreviation of a word follows the form <first letter><number><last letter>. Be ...
- Unique Word Abbreviation -- LeetCode
An abbreviation of a word follows the form <first letter><number><last letter>. Be ...
随机推荐
- block fomating context
http://www.w3help.org/zh-cn/kb/010/ 它与普通的块框类似,不同之处在于: 1可以包含浮动元素 2可以阻止外边距折叠 3可以防止元素被浮动元素覆盖 placeholde ...
- java IO流 Zip文件操作
一.简介 压缩流操作主要的三个类 ZipOutputStream.ZipFile.ZipInputStream ,经常可以看到各种压缩文件:zip.jar.GZ格式的压缩文件 二.ZipEntry ...
- jQuery实现全选效果【转】
这是一段用jquery实现全选的代码,主要思路如下: 1.所有的复选框都有单击事件,所有效果都是在单击事件下实现的 2.全选复选框所实现的功能与其他复选选项实现的功能不同,所有在单击事件内做一个判断, ...
- css 图片内容在不同分辨率下居中显示(演示的图片宽度是1920px,当图片宽度大于显示屏的宽度时)
1.img 图片内容在不同分辨率下居中显示(如果隐藏多余,在img外面套一个div 设定overflow: hidden.div的大小就是img显示区域的大小) <!DOCTYPE html& ...
- Java抽象类与接口的区别
很多常见的面试题都会出诸如抽象类和接口有什么区别,什么情况下会使用抽象类和什么情况你会使用接口这样的问题.本文我们将仔细讨论这些话题. 在讨论它们之间的不同点之前,我们先看看抽象类.接口各自的特性. ...
- Moneybookers API支付方式开发 步骤
开发文档: 支付说明手册 步骤: 1.使用商家帐号,登录到www.moneybookers.com,核对商家信息是否正确. 2.在账户-->商家工具(设置) a.API/MQI password ...
- Visual Studio 2010编译时总是提示"调用目标发生了异常"的解决
现象: 无论建立的是Win32 Console的解决方案,还是MFC的解决方案,重新打开Visual Studio 2010之后,编译时总是提示“调用的目标发生了异常” 解决: 1. 关闭Visual ...
- MongoDB数据库的操作,增删改查
在student集合中插入一些数据 db.student.insert({ "学号":10010, "姓名":"德莱文", "年龄 ...
- css解决div的各种浏览器兼容性问题
方法一: min-height:500px;/*解决ie8.9.ff.chromet*/ height:100%;/*解决ie6.7*/ _height:500px;/*解决ie6超出自动溢出*/ 方 ...
- Maven环境搭建
1,下载maven zip版 http://maven.apache.org/download.cgi 2,配置maven环境变量 (1) 新建MAVEN_HOME环境变量 E:\TOOLS\A ...