# 通过解决“构造包含所有给定子串的最短字符串”问题思考算法优化

## 域名选择

<题目来源：百度2017秋招，http://exercise.acmcoder.com/... >

#### 问题描述

3
ABC
CBA
AB

5

ABC__
__CBA
AB___

a.没有重叠部分
abcdef
cdgvp
hik

abcdefcdgvphik

b.有重叠部分
abcdef
cdefgh
xyzab

abcdefghxyzab

et->abcetfgh->fgh (最佳构造方案)
2+3
abcetfgh->et->fgh (非最佳)
2+0
abcetfgh->fgh->et (非最佳)
3+0

c.存在子串的情况

f
dfg

f[i|(1<<k), k] = max{f[i|(1<<k), k], f[i, j] + overlap[j, k]}

a.判断x的二进制位中的第i位是否为1
x & (1 << i)

b.将x的二进制位中的第i位置为1
x | (1 << i)

*关于全排列算法

http://www.cnblogs.com/noworn...

*TSP问题的其他算法：
a.分支限界
b.贪心
c.含剪枝的深度优先搜索(DFS)
http://blog.csdn.net/q_l_s/ar...

``````import sys
import itertools

def combine_words(wa, wb):
max_overlap_len = min(len(wa), len(wb))
for overlap_len in range(max_overlap_len - 1, -1, -1):
match_f = True
for i in range(overlap_len):
if wa[len(wa) - overlap_len + i] != wb[i]:
match_f = False
break

if match_f:
return overlap_len

def calc_each_overlap(words_slv, n_slv, overlap):
for i in range(n_slv):
for j in range(n_slv):
if i != j:
overlap[i][j] = combine_words(words_slv[i], words_slv[j])

def dp(n, overlap):
opt = [[0 for i in range(n)] for i in range(1 << (n + 1))]

for i in range(1, 1 << n):
for j in range(n):
if i & (1 << j):
for k in range(n):
if (i & (1 << k)) == 0 and opt[i | (1 << k)][k] < opt[i][j] + overlap[j][k]:
opt[i | (1 << k)][k] = opt[i][j] + overlap[j][k]

ans = 0
for i in range(n):
ans = max(opt[(1 << n) - 1][i], ans)
return ans

def main():
words = []
for i in range(n):

sub_f = [False for i in range(n)]
for i in range(n):
for j in range(n):
if i != j and ''.join(words[i]).find(''.join(words[j])) != -1:
sub_f[j] = True

words_slv = []
t_len = 0
n_slv = 0
for i in range(n):
if not sub_f[i]:
n_slv += 1
t_len += len(words[i])
words_slv.append(words[i])

overlap = [[0 for i in range(n_slv)] for i in range(n_slv)]
calc_each_overlap(words_slv, n_slv, overlap)

t_overlap_len = dp(n_slv, overlap)
print t_len - t_overlap_len

# per = [i for i in range(n_slv)]
# shortest_words = sys.maxint
# for permutation in itertools.permutations(per, n_slv):
#     total_words_len = 0
#     total_overlap_len = 0
#     for i in range(n_slv):
#         total_words_len += len(words_slv[permutation[i]])
#         if i + 1 < n_slv:
#             total_overlap_len += overlap[permutation[i]][permutation[i + 1]]
#             if total_overlap_len >= shortest_words:
#                 break
#
#     if total_words_len - total_overlap_len < shortest_words:
#         shortest_words = total_words_len - total_overlap_len
#
# print shortest_words

if __name__ == '__main__':
main()``````

1 人关注
12 篇文章