CF1037H. Security
Solution 1
设原串为ststst。
对于单个询问,答案必然是询问串sss的一个前缀s[1..i]s[1..i]s[1..i]加上一个大于s[i+1]s[i+1]s[i+1]的字符ccc构成。
因此我们只需要枚举前缀s[1..i]s[1..i]s[1..i],枚举字符ccc,快速询问s[1..i]+cs[1..i]+cs[1..i]+c有没有在st[l,r]st[l,r]st[l,r]中出现过,后缀自动机+线段树合并,记录区间内存在的末尾位置个数即可。
时间复杂度O(26∗nlgn)O(26*nlgn)O(26∗nlgn)
Solution 2
我们发现我们用线段树合并记录区间末尾位置个数并不优,我们考虑直接记录区间内是否有ccc的可行转移,因为字符集只有262626,我们可以把它压成2262^{26}226的intintint,即可快速判断是否可以转移。
时间复杂度O((26+lgn)∗n)O((26+lgn)*n)O((26+lgn)∗n)
Code 1
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second
using namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=400005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
char St[MAXN],st[MAXN];
int ls[MAXN*20],rs[MAXN*20],s[MAXN*20],rt[MAXN],nw[MAXN],nodenum=0;
void print(int x,int y)
{for (int i=1;i<=x;i++) putchar(St[i]);putchar(y+'a');puts("");
}int query(int x,int l,int r,int L,int R)
{if (L>R||!x) return 0;if (l>=L&&r<=R) return s[x];int mid=(l+r)>>1;if (R<=mid) return query(ls[x],l,mid,L,R);else if (L>mid) return query(rs[x],mid+1,r,L,R);else return query(ls[x],l,mid,L,mid)+query(rs[x],mid+1,r,mid+1,R);
}
int merge(int x,int y)
{if (!x||!y) return x|y;int z=++nodenum;s[z]=s[x]+s[y];ls[z]=merge(ls[x],ls[y]);rs[z]=merge(rs[x],rs[y]);return z;
}
int update(int x,int l,int r,int y)
{if (!x) x=++nodenum;s[x]++;if (l==r) return x;int mid=(l+r)>>1;if (y<=mid) ls[x]=update(ls[x],l,mid,y);else rs[x]=update(rs[x],mid+1,r,y); return x;
}int t[MAXN][26],len[MAXN],fa[MAXN],Lst[MAXN],sz=2,lst=1;
void insert(int c,int id)
{int p=lst,np=lst=sz++;len[np]=len[p]+1,Lst[id]=np;for (;p&&!t[p][c];p=fa[p]) t[p][c]=np;if (!p) { fa[np]=1; return; }int q=t[p][c];if (len[q]==len[p]+1) fa[np]=q;else{int nq=sz++;fa[nq]=fa[q];fa[np]=fa[q]=nq;len[nq]=len[p]+1;memcpy(t[nq],t[q],sizeof t[0]);for (;t[p][c]==q;p=fa[p]) t[p][c]=nq;}
}
int c[MAXN]={1},a[MAXN];
void Init()
{for (int i=1;i<sz;i++) c[i]=0;for (int i=1;i<sz;i++) c[len[i]]++;for (int i=1;i<sz;i++) c[i]+=c[i-1];for (int i=sz-1;i>=1;i--) a[--c[len[i]]]=i;for (int i=sz-1;i>=1;i--) rt[fa[a[i]]]=merge(rt[fa[a[i]]],rt[a[i]]);
}
signed main()
{scanf("%s",st+1);int len=strlen(st+1);for (int i=1;i<=len;i++) insert(st[i]-'a',i);for (int i=1;i<=len;i++) rt[Lst[i]]=update(rt[Lst[i]],1,sz,i);Init();int Case=read();while (Case--){int l=read(),r=read();scanf("%s",St+1);int Len=strlen(St+1),id=Len+1;nw[0]=1;for (int i=1;i<=Len;i++){if (t[nw[i-1]][St[i]-'a']&&query(rt[t[nw[i-1]][St[i]-'a']],1,sz,l+i-1,r)) nw[i]=t[nw[i-1]][St[i]-'a'];else { id=i; break; }}int flag=0;for (int i=id;i>=1;i--){for (int j=(i>Len?0:St[i]-'a'+1);j<26;j++)if (t[nw[i-1]][j]&&query(rt[t[nw[i-1]][j]],1,sz,l+i-1,r)) { print(i-1,j),flag=1; break; } if (flag) break;}if (!flag) puts("-1");}return 0;
}
Code 2
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second
using namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=1e9+7;
const int MAXN=400005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
char St[MAXN],st[MAXN];
int ls[MAXN*20],rs[MAXN*20],s[MAXN*20],rt[MAXN],nw[MAXN],Q[MAXN],nodenum=0;
void print(int x,int y)
{for (int i=1;i<=x;i++) putchar(St[i]);int t=0;while (!(y&1)) y>>=1,t++;putchar(t+'a');puts("");
}int query(int x,int l,int r,int L,int R)
{if (L>R||!x) return 0;if (l>=L&&r<=R) return s[x];int mid=(l+r)>>1;if (R<=mid) return query(ls[x],l,mid,L,R);else if (L>mid) return query(rs[x],mid+1,r,L,R);else return query(ls[x],l,mid,L,mid)|query(rs[x],mid+1,r,mid+1,R);
}
int merge(int x,int y)
{if (!x||!y) return x|y;int z=++nodenum;s[z]=s[x]|s[y];ls[z]=merge(ls[x],ls[y]);rs[z]=merge(rs[x],rs[y]);return z;
}
int update(int x,int l,int r,int y,int z)
{if (!x) x=++nodenum;s[x]|=z;if (l==r) return x;int mid=(l+r)>>1;if (y<=mid) ls[x]=update(ls[x],l,mid,y,z);else rs[x]=update(rs[x],mid+1,r,y,z); return x;
}int t[MAXN][26],len[MAXN],fa[MAXN],Lst[MAXN],sz=2,lst=1;
void insert(int c,int id)
{int p=lst,np=lst=sz++;len[np]=len[p]+1,Lst[id]=np;for (;p&&!t[p][c];p=fa[p]) t[p][c]=np;if (!p) { fa[np]=1; return; }int q=t[p][c];if (len[q]==len[p]+1) fa[np]=q;else{int nq=sz++;fa[nq]=fa[q];fa[np]=fa[q]=nq;len[nq]=len[p]+1;memcpy(t[nq],t[q],sizeof t[0]);for (;t[p][c]==q;p=fa[p]) t[p][c]=nq;}
}
int c[MAXN]={1},a[MAXN];
void Init()
{for (int i=1;i<sz;i++) c[i]=0;for (int i=1;i<sz;i++) c[len[i]]++;for (int i=1;i<sz;i++) c[i]+=c[i-1];for (int i=sz-1;i>=1;i--) a[--c[len[i]]]=i;for (int i=sz-1;i>=1;i--) rt[fa[a[i]]]=merge(rt[fa[a[i]]],rt[a[i]]);
}
signed main()
{scanf("%s",st+1);int len=strlen(st+1); Lst[0]=1;for (int i=1;i<=len;i++) insert(st[i]-'a',i);for (int i=1;i<=len;i++) rt[Lst[i-1]]=update(rt[Lst[i-1]],0,sz,i-1,1<<(st[i]-'a'));Init();int Case=read();while (Case--){int l=read(),r=read();scanf("%s",St+1);int Len=strlen(St+1),id=Len;nw[0]=1;for (int i=1;i<=Len;i++){if (((Q[i-1]=query(rt[nw[i-1]],0,sz,l+i-2,r-1))>>(St[i]-'a'))&1) nw[i]=t[nw[i-1]][St[i]-'a'];else { id=i-1; break; }}Q[Len]=query(rt[nw[Len]],0,sz,l+Len-1,r-1);int flag=0;for (int i=id;i>=0;i--){int p=Q[i],q=(i>=Len?0:St[i+1]-'a'+1);if (p>=(1<<q)) { p^=p&((1<<q)-1),print(i,p&(-p)),flag=1; break; }}if (!flag) puts("-1");}return 0;
}