思路
答案一定可以是输入的字符串中的一个,因为若答案字符串长这样(红色)
完全可以去掉分割线右边多余的,不影响答案
此时答案变成,是否能找到一个字符串,使得这个字符串包含了恰好K-1个其他字符串
暴力枚举的时间复杂度是 ,但是看图可知,这个答案如果要包含其他字符串,一定其他字符串是他的前缀,于是可以想到用字典树
枚举字典树进行dfs,记 为恰好在编号x结束的字符串数量,当遍历到某处,在此时的
之和恰好等于k时,该字符串便是答案。
#include <iostream>
#include <vector>
using namespace std;
const int N=2e5+7;
int son[N][2];//编号为u的节点的26个儿子
int cnt1[N];//恰好在编号p就结束的字符串数量
int idx;//编号
int n,k;
void insert(string& s){
int p=0;
for(int i=0;i<s.size();i++){
int u=s[i]-'0';
if(!son[p][u])son[p][u]=++idx;
p=son[p][u];
}
cnt1[p]++;
}
vector<char> ans;
string s="";
void dfs(int p,int size){
if(size==k){
for(int i=0;i<ans.size();i++){
s+=ans[i];
}
return;
}
if(size>k)return;
for(int i=0;i<2 &&!s.size();i++){
int q=son[p][i];
if(!q)continue;
ans.push_back(i+'0');
dfs(q,size+cnt1[q]);
ans.pop_back();
}
}
int main(){
ios::sync_with_stdio(false),cin.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
string s;
cin>>s;
insert(s);
}
dfs(0,0);
if(s.size())cout<<s<<"\n";
else cout<<-1;
}
跑出来7ms,900kb,时间和空间都非常良好,现在分析时间复杂度。
由于在Trie上dfs,Trie上每个节点最多被访问一次,当size==k或size>k时结束,而k的量级与相同,故时间复杂度不会超过
,空间复杂度也不会超过

京公网安备 11010502036488号