这道题属于进阶难度的题,我们该如何思考呢,我们用一个hash公式把字符串的前缀都保存下来,然后我们在进行查找。具体解释在以下代码中。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>pi;
void member()
{
int x;cin>>x;
string p[x];
map<int,int>mp;
vector<pi>l;//储存类型第一个储存哈希公式储存起来的字符串,第二个是对应判断输入字符串组的下标
for(int i=1;i<=x;i++)
{
string y;cin>>y;
p[i]=y;
int ha=0;
for(int i1=0;i1<y.size();i1++)
{
ha=ha*3+y[i1]-'0'+1;//将每一个字符串的前缀用一个哈希公式换算成数字保存下来
if(!mp[ha])mp[ha]=i;//map的始初化为0,所以这个时候是判断是否进行过赋值操作 如果没有进行过的话直接赋值
else
{
if(p[i]<p[mp[ha]])mp[ha]=i;//如果该字符前缀的字典序小于这个保存下来的字符前缀的字典序我们只保留这个最小字典序
}
}
}
for(auto k:mp)l.push_back({k.first,k.second});//用一个指针将mp里面的元素压入l中
int hu;cin>>hu;
while(hu--)//进行判断操作
{
string fin;cin>>fin;
int pan=0;
string ti;
for(int i=0;i<fin.size();i++)
{
pan=pan*3+fin[i]-'0'+1;//扫面用同一个哈希公式保存字符串前缀
pi dai={pan,0};//方便查找
auto op=lower_bound(l.begin(),l.end(),dai);//这个查找方式的内在使用算法就是二分查找找出第一个与pan相等的
if((*op).first==pan)ti=p[(*op).second];//进一步判断因为上面的lower_bound可能会找出比pan大的
//最后随着前缀递增我们可以找出最大前缀
}
cout<<ti<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);/*上面两行是将cin,conut输入,输出流和scanf printf输入,输出流同步*/
int x;cin>>x;
while(x--)
{
member();
}
}