|
|
|
|
package class46;
|
|
|
|
|
|
|
|
|
|
public class Problem_0411_MinimumUniqueWordAbbreviation {
|
|
|
|
|
|
|
|
|
|
// 区分出来之后,缩写的长度,最短是多少?
|
|
|
|
|
public static int min = Integer.MAX_VALUE;
|
|
|
|
|
|
|
|
|
|
// 取得缩写的长度最短的时候,决定是什么(fix)
|
|
|
|
|
public static int best = 0;
|
|
|
|
|
|
|
|
|
|
public static int abbrLen(int fix, int len) {
|
|
|
|
|
int ans = 0;
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
if ((fix & (1 << i)) != 0) {
|
|
|
|
|
ans++;
|
|
|
|
|
if (cnt != 0) {
|
|
|
|
|
ans += 1;
|
|
|
|
|
}
|
|
|
|
|
cnt = 0;
|
|
|
|
|
} else {
|
|
|
|
|
cnt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (cnt != 0) {
|
|
|
|
|
ans += 1;
|
|
|
|
|
}
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 原始的字典,被改了
|
|
|
|
|
// target : abc 字典中的词 : bbb -> 101 -> int ->
|
|
|
|
|
// fix -> int -> 根本不用值,用状态 -> 每一位保留还是不保留的决定
|
|
|
|
|
public static boolean canFix(int[] words, int fix) {
|
|
|
|
|
for (int word : words) {
|
|
|
|
|
if ((fix & word) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 利用位运算加速
|
|
|
|
|
public static String minAbbreviation1(String target, String[] dictionary) {
|
|
|
|
|
min = Integer.MAX_VALUE;
|
|
|
|
|
best = 0;
|
|
|
|
|
char[] t = target.toCharArray();
|
|
|
|
|
int len = t.length;
|
|
|
|
|
int siz = 0;
|
|
|
|
|
for (String word : dictionary) {
|
|
|
|
|
if (word.length() == len) {
|
|
|
|
|
siz++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int[] words = new int[siz];
|
|
|
|
|
int index = 0;
|
|
|
|
|
for (String word : dictionary) {
|
|
|
|
|
if (word.length() == len) {
|
|
|
|
|
char[] w = word.toCharArray();
|
|
|
|
|
int status = 0;
|
|
|
|
|
for (int j = 0; j < len; j++) {
|
|
|
|
|
if (t[j] != w[j]) {
|
|
|
|
|
status |= 1 << j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
words[index++] = status;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dfs1(words, len, 0, 0);
|
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
if ((best & (1 << i)) != 0) {
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
builder.append(count);
|
|
|
|
|
}
|
|
|
|
|
builder.append(t[i]);
|
|
|
|
|
count = 0;
|
|
|
|
|
} else {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
builder.append(count);
|
|
|
|
|
}
|
|
|
|
|
return builder.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 所有字典中的单词现在都变成了int,放在words里
|
|
|
|
|
// 0....len-1 位去决定保留还是不保留!当前来到index位
|
|
|
|
|
// 之前做出的决定!
|
|
|
|
|
public static void dfs1(int[] words, int len, int fix, int index) {
|
|
|
|
|
if (!canFix(words, fix)) {
|
|
|
|
|
if (index < len) {
|
|
|
|
|
dfs1(words, len, fix, index + 1);
|
|
|
|
|
dfs1(words, len, fix | (1 << index), index + 1);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 决定是fix,一共的长度是len,求出缩写是多长?
|
|
|
|
|
int ans = abbrLen(fix, len);
|
|
|
|
|
if (ans < min) {
|
|
|
|
|
min = ans;
|
|
|
|
|
best = fix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 进一步设计剪枝,注意diff的用法
|
|
|
|
|
public static String minAbbreviation2(String target, String[] dictionary) {
|
|
|
|
|
min = Integer.MAX_VALUE;
|
|
|
|
|
best = 0;
|
|
|
|
|
char[] t = target.toCharArray();
|
|
|
|
|
int len = t.length;
|
|
|
|
|
int siz = 0;
|
|
|
|
|
for (String word : dictionary) {
|
|
|
|
|
if (word.length() == len) {
|
|
|
|
|
siz++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int[] words = new int[siz];
|
|
|
|
|
int index = 0;
|
|
|
|
|
// 用来剪枝
|
|
|
|
|
int diff = 0;
|
|
|
|
|
for (String word : dictionary) {
|
|
|
|
|
if (word.length() == len) {
|
|
|
|
|
char[] w = word.toCharArray();
|
|
|
|
|
int status = 0;
|
|
|
|
|
for (int j = 0; j < len; j++) {
|
|
|
|
|
if (t[j] != w[j]) {
|
|
|
|
|
status |= 1 << j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
words[index++] = status;
|
|
|
|
|
diff |= status;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dfs2(words, len, diff, 0, 0);
|
|
|
|
|
StringBuilder builder = new StringBuilder();
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
|
if ((best & (1 << i)) != 0) {
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
builder.append(count);
|
|
|
|
|
}
|
|
|
|
|
builder.append(t[i]);
|
|
|
|
|
count = 0;
|
|
|
|
|
} else {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
builder.append(count);
|
|
|
|
|
}
|
|
|
|
|
return builder.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void dfs2(int[] words, int len, int diff, int fix, int index) {
|
|
|
|
|
if (!canFix(words, fix)) {
|
|
|
|
|
if (index < len) {
|
|
|
|
|
dfs2(words, len, diff, fix, index + 1);
|
|
|
|
|
if ((diff & (1 << index)) != 0) {
|
|
|
|
|
dfs2(words, len, diff, fix | (1 << index), index + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
int ans = abbrLen(fix, len);
|
|
|
|
|
if (ans < min) {
|
|
|
|
|
min = ans;
|
|
|
|
|
best = fix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|