You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.8 KiB

2 years ago
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) {
2 years ago
ans += 1;
2 years ago
}
cnt = 0;
} else {
cnt++;
}
}
if (cnt != 0) {
2 years ago
ans += 1;
2 years ago
}
return ans;
}
// 原始的字典,被改了
2 years ago
// target : abc 字典中的词 : bbb -> 101 -> int ->
2 years ago
// 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;
}
}
}
}