The 15th Chinese Northeast L. k-th Smallest Common Substring
题意描述:
给你多个串,有多个询问,每次询问需要查询第k小所有模式串的共有子串,如果没有,输出-1,如果有输出该子串在第一个串中的第一次出现的位置
思路:
判断子串是否为公共串只需要染色即可,弦论那题可以询问第k小字典序子串,但是询问过多,明显会T,所以要转换思路,我们如果对字符串建反串,可以发现从反串的父节点出发,可以根据父结点与子节点相交位置来排序,然后根据这个方向去dfs的dfs序,就是字典序,如假设翻转串eabc,edbc的父结点都为bc,那根据dfs序明显先去eabc,而eabc的原串也确实是字典序小与edbc的原串的,所以我们根据建立的dfs序来遍历即是按照字典序来遍历了,利用前缀和二分思想即可查询第k小字典序,因为需要找在第一个串中的第一个出现位置,即翻转串的endpos最大的位置,所以在插入的时候再记录一个1串的endpos,再dfs一遍将所有在一串的子串endpos取大,最后输出答案即可,注意前缀和可能爆int,所以要将前缀和设为long long
#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N=1e6+10;
typedef long long ll;
int n,m,q,tot,last,len[N],fa[N],ch[N][26];
ll pre[N];
int col[N],vis[N],endps[N];
pair<int,int>endpos[N];
string s;
string ss[N];
struct point {
int to,w;
};
vector<point>v[N];
int cmp(point a,point b) {
return a.w<b.w;
}
int Ins(int c,int last,pair<int,int>nowk) {
int kk=nowk.first;
int kpos=nowk.second;
int p=last;
if(ch[p][c]) {
int q=ch[p][c];
if(len[p]+1==len[q]) {
return q;
} else {
int nq=++tot;
len[nq]=len[p]+1;
endpos[nq]=endpos[q];
endps[nq]=endps[q];
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];
fa[q]=nq;
for(; p&&ch[p][c]==q; p=fa[p])ch[p][c]=nq;
return nq;
}
}
int np=++tot;
len[np]=len[p]+1;
endpos[tot]=nowk;
if(kk==1)endps[tot]=kpos;
for(; p&&!ch[p][c]; p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1;
else {
int q=ch[p][c];
if(len[p]+1==len[q])fa[np]=q;
else {
int nq=++tot;
len[nq]=len[p]+1;
endpos[nq]=endpos[q];
endps[nq]=endps[q];
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for(; p&&ch[p][c]==q; p=fa[p])ch[p][c]=nq;
}
}
return np;
}
int pot[N];
int tid;
int viss[N];
inline void dfs(int x) {
sort(v[x].begin(),v[x].end(),cmp);
for(int i=0; i<v[x].size(); i++) {
int y=v[x][i].to;
if(vis[y]==m) {
pot[++tid]=y;
dfs(y);
}
}
}
inline void dfs1(int x) {
for(int i=0; i<v[x].size(); i++) {
int y=v[x][i].to;
dfs1(y);
endps[x]=max(endps[x],endps[y]);
}
}
signed main() {
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--) {
for(int i=0;i<=tot+10;i++){
memset(ch[i],0,sizeof(ch[i]));
col[i]=0;
vis[i]=0;
len[i]=0;
fa[i]=0;
pot[i]=0;
endps[i]=0;
v[i].clear();
endpos[i].first=0;
endpos[i].second=0;
endps[i]=0;
}
cin>>m;
tot=1;
tid=0;
for(int i=1; i<=m; i++) {
last=1;
cin>>ss[i];
n=ss[i].length();
reverse(ss[i].begin(),ss[i].end());
for(int j=0; j<n; j++)
last=Ins(ss[i][j]-'a',last, {i,j+1});
}
for(int i=1; i<=m; i++) {
int pos=1;
int len=ss[i].length();
for(int j=0; j<len; j++) {
pos=ch[pos][ss[i][j]-'a'];
int p=pos;
for(; p&&col[p]!=i; p=fa[p]) {
if(i==1)viss[p]++;
vis[p]++;
col[p]=i;
}
}
}
for(int i=2; i<=tot; i++) {
v[fa[i]].push_back({i,ss[endpos[i].first][endpos[i].second-len[fa[i]]-1]-'a'});
}
dfs(1);
dfs1(1);
for(int i=1; i<=tid; i++) {
pre[i]=pre[i-1]+len[pot[i]]-len[fa[pot[i]]];
}
cin>>q;
for(int i=1;i<=q;i++) {
int x;
cin>>x;
if(x>pre[tid])cout<<-1<<'\n';
else {
int sid=lower_bound(pre+1,pre+1+tid,x)-pre;
int l = ss[1].length()-endps[pot[sid]];
int r = l+len[fa[pot[sid]]]+( x-pre[sid-1]);
cout<<l<<" "<<r<<'\n';
}
}
}
}

浙公网安备 33010602011771号