P12294
xujindong_ · · 题解
如果你做过 AT_agc022_e 或 gym102586J,可以知道这种将 01 串中连续三个替换为一个字符的问题可以造一个自动机判定。
考虑直接根据等价关系建自动机,根据 Myhill-Nerode 定理,
考虑怎么输出方案,假设 solve(l,r,type) 表示区间
判定子区间能否合成,可以用倍增维护自动机每个节点从
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int t,n,g[65536],p[1029],type[1029],id[105];
char a[100005];
string opt;
vector<bool>l[1029];
bool cmp(int a,int b){
return l[a]==l[b]?a<b:l[a]<l[b];
}
bool dfs(int s,string opt,int t){
if((__lg(s)&1)!=(__lg(t)&1))return g[s]=0;
if(g[s]!=-1)return g[s];
for(int i=0;i<__lg(s)-2;i++)if(dfs(s>>(i+3)<<(i+1)|(opt[s>>i&7]-'0')<<i|(s&((1<<i)-1)),opt,t))return g[s]=1;
return g[s]=0;
}
struct DFA{
int tr[50][2],cnt,s,f[15][3130][50];
bool b[50];
void build(string opt,int t){
int num=0;
cnt=0,memset(g,-1,sizeof(g)),g[2]=g[3]=g[4]=g[5]=g[6]=g[7]=0,g[t]=1;
for(int lenx=0;lenx<=9;lenx++){
for(int x=1<<lenx;x<2<<lenx;x++){
l[x].clear(),p[++num]=x;
for(int leny=0;leny<=6;leny++)for(int y=1<<leny;y<2<<leny;y++)l[x].push_back(dfs(y<<__lg(x)|(x&~(1<<__lg(x))),opt,t));
}
}
sort(p+1,p+num+1,cmp);
for(int i=1;i<=num;i++){
if(l[p[i]]!=l[p[i-1]])id[++cnt]=p[i];
type[p[i]]=cnt;
}
s=type[1];
for(int i=1;i<=cnt;i++)tr[i][0]=type[3<<__lg(id[i])^id[i]],tr[i][1]=type[3<<__lg(id[i])|id[i]];
for(int i=1;i<=cnt;i++)b[i]=dfs(id[i],opt,t);
}
void init(int n,char a[]){
for(int i=1;i<n>>5;i++){
for(int j=1;j<=cnt;j++)f[0][i][j]=j;
for(int j=i<<5;j<(i+1)<<5;j++)for(int k=1;k<=cnt;k++)f[0][i][k]=tr[f[0][i][k]][a[j]-'0'];
}
for(int i=1;i<=__lg(n)-5;i++)for(int j=1;j+(1<<i)<=n>>5;j++)for(int k=1;k<=cnt;k++)f[i][j][k]=f[i-1][j+(1<<(i-1))][f[i-1][j][k]];
}
bool check(int l,int r){
int pos=s;
while(l<=r&&l&31)pos=tr[pos][a[l++]-'0'];
for(int i=__lg(n)-5;i>=0;i--)if(l+(1<<(i+5))<=r)pos=f[i][l>>5][pos],l+=1<<(i+5);
while(l<=r)pos=tr[pos][a[l++]-'0'];
return b[pos];
}
}d[6];
void solve(int l,int r,int type){
if(l==r){
putchar(a[l]);
return;
}
if(type<=1){
for(int i=l,j=r;i<=j;i+=2,j-=2){
for(int k=0;k<8;k++){
if(opt[k]==type+'0'&&d[k&1].check(l,i)&&d[(k>>1)+2].check(i+1,r)){
putchar('('),solve(l,i,k&1),solve(i+1,r,(k>>1)+2),putchar(')');
return;
}
if(opt[k]==type+'0'&&d[(k&3)+2].check(l,j-1)&&d[k>>2].check(j,r)){
putchar('('),solve(l,j-1,(k&3)+2),solve(j,r,k>>2),putchar(')');
return;
}
}
}
}
else{
for(int i=l,j=r;i<=j;i+=2,j-=2){
if(d[(type-2)&1].check(l,i)&&d[(type-2)>>1].check(i+1,r)){
solve(l,i,(type-2)&1),solve(i+1,r,(type-2)>>1);
return;
}
if(d[(type-2)&1].check(l,j-1)&&d[(type-2)>>1].check(j,r)){
solve(l,j-1,(type-2)&1),solve(j,r,(type-2)>>1);
return;
}
}
}
}
int main(){
cin>>opt>>t;
for(int i=0;i<6;i++)d[i].build(opt,i+2);
while(t--){
cin>>a+1,n=strlen(a+1);
for(int i=0;i<6;i++)d[i].init(n,a);
if(!d[1].check(1,n))puts("-1");
else solve(1,n,1),putchar('\n');
}
return 0;
}