难度中等155
给定一个字符串数组 arr
,字符串 s
是将 arr
某一子序列字符串连接所得的字符串,如果 s
中的每一个字符都只出现过一次,那么它就是一个可行解。
请返回所有可行解 s
中最长长度。
示例 1:
输入:arr = ["un","iq","ue"]
输出:4
解释:所有可能的串联组合是 "","un","iq","ue","uniq" 和 "ique",最大长度为 4。
示例 2:
输入:arr = ["cha","r","act","ers"]
输出:6
解释:可能的解答有 "chaers" 和 "acters"。
示例 3:
输入:arr = ["abcdefghijklmnopqrstuvwxyz"]
输出:26
提示:
1 <= arr.length <= 16
1 <= arr[i].length <= 26
arr[i]
中只含有小写英文字母
思路:用DFS枚举每个串的选与不选的状态,复杂度为O(2^16)。
1.回溯法。
class Solution {
public:
void DFS(int i, int& n, bool notValid[], vector<string>& arr, int states[], int state, int len, int& ans)
{
if(i == n)
{
ans = max(ans, len);
return;
}
if(!notValid[i] && (states[i] & state) == 0)//如果当前字符串可以加进去
{
DFS(i + 1, n, notValid, arr, states, states[i] ^ state, len + arr[i].size(), ans);
}
//考虑不加进去的情况
DFS(i + 1, n, notValid, arr, states, state, len, ans);
}
int maxLength(vector<string>& arr) {
int i, j, state, n = arr.size(), states[n + 5], ans = 0, temp;
bool notValid[n + 5];
memset(notValid, 0, sizeof(notValid));
for(i = 0; i < n; ++ i)
{
state = 0;
for(j = arr[i].size() - 1; j >= 0; -- j)
{
temp = 1 << (arr[i][j] - 'a');
if(state & temp)//这个字符串不合法
{
notValid[i] = true;
break;
}
state |= temp;
}
states[i] = state;
}
DFS(0, n, notValid, arr, states, 0, 0, ans);
return ans;
}
};
2.使用后缀和进行减枝版本:
class Solution {
public:
void DFS(int i, int& n, bool notValid[], vector<string>& arr, int states[], int suffixSum[], int state, int len, int& ans)
{
if(suffixSum[i] + len < ans)//如果把后面所有的字符串都连上都不能拿到更大的答案 减枝
{
return;
}
if(i == n)
{
ans = max(ans, len);
return;
}
if(!notValid[i] && (states[i] & state) == 0)//如果当前字符串可以加进去
{
DFS(i + 1, n, notValid, arr, states, suffixSum, states[i] ^ state, len + arr[i].size(), ans);
}
//考虑不加进去的情况
DFS(i + 1, n, notValid, arr, states, suffixSum, state, len, ans);
}
int maxLength(vector<string>& arr) {
int i, j, state, n = arr.size(), states[n + 5], suffixSum[n + 5], ans = 0, temp;
bool notValid[n + 5];
memset(notValid, 0, sizeof(notValid));
for(i = 0; i < n; ++ i)
{
state = 0;
for(j = arr[i].size() - 1; j >= 0; -- j)
{
temp = 1 << (arr[i][j] - 'a');
if(state & temp)//这个字符串不合法
{
notValid[i] = true;
break;
}
state |= temp;
}
states[i] = state;
}
suffixSum[n] = 0;
for(i = n - 1; i >= 0; -- i)
{
suffixSum[i] = suffixSum[i + 1] + arr[i].size();
}
DFS(0, n, notValid, arr, states, suffixSum, 0, 0, ans);
return ans;
}
};