思路

答案一定可以是输入的字符串中的一个,因为若答案字符串长这样(红色)

alt

完全可以去掉分割线右边多余的,不影响答案

此时答案变成,是否能找到一个字符串,使得这个字符串包含了恰好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的量级与相同,故时间复杂度不会超过,空间复杂度也不会超过