题意
传送门 LeeCode 472 连接词
题解
令单词数量为 n n n,单词长度为 m m m。 d p [ i ] dp[i] dp[i] 代表单词 s s s 从位置 i i i 到结尾处,能否由至少一个较短单词构成,边界条件 d p [ m ] = 1 dp[m]=1 dp[m]=1。可以通过建 T r i e Trie Trie, O ( m ) O(m) O(m) 枚举以 s [ i ] s[i] s[i] 为开头的较短单词,记忆化求解。总时间复杂度 O ( n m 2 ) O(nm^2) O(nm2)。
class Solution
{
const int MAXN = 1E3 + 5, MAXS = 1E5 + 5;
public:
bool dp[MAXN];
int rt, n, ch[MAXS][26];
bool end[MAXS];
int build()
{
memset(ch[n], -1, sizeof(ch[n]));
end[n] = 0;
return n++;
}
void insert(string &s)
{
int p = rt, len = s.size();
for (int i = 0; i < len; ++i)
{
int c = s[i] - 'a';
if (ch[p][c] == -1)
ch[p][c] = build();
p = ch[p][c];
}
end[p] = 1;
}
bool rec(string &s, int k)
{
if (k == (int)s.size())
return 1;
bool &res = dp[k];
int p = rt;
for (int i = k; i < (int)s.size(); ++i)
{
int c = s[i] - 'a';
if (ch[p][c] == -1)
break;
p = ch[p][c];
if (end[p] && rec(s, i + 1))
{
res = 1;
break;
}
}
return res;
}
vector<string> findAllConcatenatedWordsInADict(vector<string> &words)
{
sort(words.begin(), words.end(), [&](string &a, string &b) -> bool
{ return a.size() < b.size(); });
n = 0;
rt = build();
vector<string> res;
for (auto &s : words)
{
if (s.size() == 0)
continue;
memset(dp, 0, sizeof(dp));
if (rec(s, 0))
res.push_back(s);
else
insert(s);
}
return res;
}
};