时间限制:
50000ms
单点时限:
5000ms
内存限制:
512MB
-
5 5 dsxmlkxp asxglqkdxp asxgavxp asxglp sxglkx kebvpyky hjpntqft asxglkxp polbmzgq jdczlmtd
样例输出
描述
我们有一个字符串集合S,其中有N个两两不同的字符串。还有M个询问,每个询问都会先给出一个字符串w,你需要回答以下三个问题:
1. 输出所有S的串中,可以由w恰好添加两个字符得到的串中,编号最小的3个。
2. 输出所有S的串中,可以由w修改不超过2个字符得到的串中,编号最小的3个。
3. 输出所有S的串中,可以由w删除恰好两个字符得到的串中,编号最小的3个。
字母可以添加在包括开头结尾在内的任意位置,比如在"abc"中添加"x"和"y",可能可以得到"yxabc","aybxc","axbyc"等等的串。
所有字符串只由小写字母构成。
输入
第一行两个数N和M,表示集合S中字符串的数量和询问的数量。
接下来N行,其中第i行给出S中第i个字符串。第i个字符串的编号就是i。
接下来M行,其中第i行给出第i个询问串。
数据范围:
N,M<=10000。
S中字符串长度和<=100000。
所有询问中字符串长度和<=100000。
输出
对每个询问输出三行,每行三个数,分别表示每个问题编号最小的3个串的编号,从小到大排列。
如果不到3个串,则在最后用-1补到3个输出,比如如果结果是1和2,那么输出1 2 -1,如果S中没有满足条件的串,就输出-1 -1 -1。
-1 -1 -1
-1 -1 -1
-1 -1 -1
1 -1 -1
-1 -1 -1
2 -1 -1
1 3 -1
4 5 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
-1 -1 -1
跟上一题一样,只是上一题的拓展。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <set>
using namespace std;
const int maxn=100000+100;
char s[maxn];
const int Max=27;
struct node
{
int sign;
int next[Max];
} a[maxn];
set<int> ve;
int cur=0;
void insert(char *s,int flg)
{
int len,ans;
int p=0;
len=strlen(s);
for(int i=0; i<len; i++)
{
ans=s[i]-'a';
if(a[p].next[ans]!=0)
{
p=a[p].next[ans];
}
else
{
a[p].next[ans]=++cur;
a[cur].sign=0;
p=a[p].next[ans];
}
}
a[p].sign=flg;
}
int len;
void find0(int sign,int p,int x)
{
if(x==len&&sign==2&&a[p].sign)
{
ve.insert(a[p].sign);
return;
}
if(sign<2&&x<=len)
{
for(int i=0; i<26; i++)
{
if(a[p].next[i]>0)
{
int tp=a[p].next[i];
find0(sign+1,tp,x);
}
}
}
if(x<len)
{
int ne=s[x]-'a';
if(a[p].next[ne]>0)
{
int tp=a[p].next[ne];
find0(sign,tp,x+1);
}
}
}
void find1(int sign,int p,int x)
{
if(x==len&&sign<=2&&a[p].sign)
{
ve.insert(a[p].sign);
return;
}
int ne=s[x]-'a';
if(sign<2&&x<=len)
{
for(int i=0; i<26; i++)
{
if(a[p].next[i]>0&&i!=ne)
{
int tp=a[p].next[i];
find1(sign+1,tp,x+1);
}
}
}
if(x<len)
{
//int ne=s[x]-'a';
if(a[p].next[ne]>0)
{
int tp=a[p].next[ne];
find1(sign,tp,x+1);
}
}
}
void find2(int sign,int p,int x)
{
if(x+(2-sign)==len&&sign<=2&&a[p].sign)
{
ve.insert(a[p].sign);
return;
}
int ne=s[x]-'a';
if(sign<=1)
find2(sign+1,p,x+1);
if(x<len)
{
if(a[p].next[ne]>0)
{
int tp=a[p].next[ne];
find2(sign,tp,x+1);
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0; i<maxn; i++)
{
cur=0;
a[i].sign=0;
memset(a[i].next,0,sizeof(a[i].next));
}
for(int i=0; i<n; i++)
{
scanf("%s",s);
insert(s,i+1);
}
for(int i=0; i<m; i++)
{
ve.clear();
scanf("%s",s);
len=strlen(s);
find0(0,0,0);
int lo=ve.size();
set<int>::iterator it;
if(lo>0)
it=ve.begin();
for(int j=0;j<3;j++)
{
if(j!=0)
printf(" ");
if(j>=lo)
printf("-1");
else
{
printf("%d",*it);
it++;
}
}
printf("\n");
ve.clear();
find1(0,0,0);
lo=ve.size();
if(lo>0)
it=ve.begin();
for(int j=0;j<3;j++)
{
if(j!=0)
printf(" ");
if(j>=lo)
printf("-1");
else
{
printf("%d",*it);
it++;
}
}
printf("\n");
ve.clear();
find2(0,0,0);
// sort(ve.begin(),ve.end());
lo=ve.size();
if(lo>0)
it=ve.begin();
for(int j=0;j<3;j++)
{
if(j!=0)
printf(" ");
if(j>=lo)
printf("-1");
else
{
printf("%d",*it);
it++;
}
}
printf("\n");
}
}
return 0;
}