题解:P11089 [ROI 2021 Day 1] 手机游戏
考虑如何确定一个保留方案合法。假设保留的下标序列为
考虑第一个段,不难发现第一个位置的字符是一定会被保留的。枚举最靠后的一个被这个字删除的位置
考虑去除无效的转移点。对于一个加入栈的元素序列,若取出其后缀进行操作,不难发现这部分元素的压入弹出操作与原先一致。因此可以直接对
具体地,我们设
最终总复杂度为
#include<bits/stdc++.h>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define repp(i,j,k) for(int i=j;i>=k;i--)
#define ls(x) (x<<1)
#define rs(x) ((x<<1)|1)
#define mp make_pair
#define sec second
#define fir first
#define pii pair<int,int>
#define lowbit(i) i&-i
#define double long double
#define int long long
#define qingbai 666
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=5e5+5,M=30,S=(1<<8)+5,inf=1e9+7;
const double eps=1e-8;
void read(int &p){
int x=0,w=1;
char ch=0;
while(!isdigit(ch)){
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
p=x*w;
}
int m,n,a[N];
bool del[M][M];
struct hash{
int base,mo,bs[N];
void init(int x,int y){
base=x,mo=y;
bs[0]=1;
rep(i,1,n)
bs[i]=bs[i-1]*base%mo;
}
int merge(int llen,int lv,int rv){
return (lv*bs[llen]+rv)%mo;
}
}H[2];
int f[N][20];
struct node{
int len,v[2];
friend node operator+(node x,node y){
node res;
res.len=x.len+y.len;
rep(i,0,1)
res.v[i]=H[i].merge(x.len,x.v[i],y.v[i]);
return res;
}
friend bool operator==(node x,node y){
return x.len==y.len&&x.v[0]==y.v[0]&&x.v[1]==y.v[1];
}
}g[N][20];
int getmin(int x,int y){
int sx=x,sy=y;
repp(i,19,0)
if(g[x][i]==g[y][i])x=f[x][i],y=f[y][i];
if(x>n)return sx;
if(y>n)return sy;
if(a[x]<a[y])return sx;
else return sy;
}
signed main(){
read(m),read(n);
rep(i,1,m){
string s;
cin>>s;
rep(j,1,m)
del[i][j]=(s[j-1]=='1');
}
string s;
cin>>s;
rep(i,1,n)
a[i]=s[i-1]-'a'+1;
rep(i,0,19)
g[n+1][i]=(node){0,{0,0}},f[n+1][i]=n+1;
H[0].init(19491001,620071201),H[1].init(19260817,998244853);
stack<int>stk;
repp(i,n,1){
f[i][0]=i+1;
while(!stk.empty()&&del[a[i]][a[stk.top()]])
f[i][0]=getmin(f[i][0],f[stk.top()][0]),stk.pop();
stk.push(i);
g[i][0]=(node){1,{a[i],a[i]}};
rep(j,1,19){
f[i][j]=f[f[i][j-1]][j-1];
g[i][j]=g[i][j-1]+g[f[i][j-1]][j-1];
}
}
for(int i=1;i<=n;i=f[i][0])
printf("%c",a[i]-1+'a');
return 0;
}