题解:P15650 [省选联考 2026] 摩卡串 / string
keep_silence · · 题解
没去省选,在家自测,做了3h牢,居然拿了90,卡了卡常,居然过了。预先声明:不知道是不是正解,复杂度也不知道,
首先,观察样例我们可以发现,字典序小于
然后再预处理 AC 自动机或 KMP 时顺便预处理如果这一位填零或一,会有多少个后缀会因为这一位而成为第二类,和有多少个后缀是
这样就能过了吗?当然不行,只有九十分,我们需要继续剪枝,对于字典图上的每个点记录匹配到哪里了,然后对于还没有包含
最后,输出方案,只需要用一个哈希表,记录每个状态和他的上一个状态以及填的什么,就可以还原出来了。
代码。
#include<bits/stdc++.h>
#include <bits/extc++.h>
#define ull unsigned long long
using namespace std;
using namespace __gnu_pbds;
int n,m,T,k;
char s[200005];
namespace AC{
struct node{
int son[2],an,fail,du,idx,g,sm[2],pr;
void init(){
memset(son,0,sizeof(son));
an=fail=idx=0;pr=0;
sm[0]=sm[1]=0;
}
}tr[205];
int tot,an[205],pid;
void init(){
tot=pid=0;
tr[0].init();
memset(an,0,sizeof(an));
}
void insert(char s[],int &idx){
int u=0;tr[u].an=0;
for(int i=1;s[i];i++){
int &son=tr[u].son[s[i]-'0'];
tr[u].g=s[i]-'0';
if(!son){
son=++tot;
tr[son].init();
}
u=son;
tr[u].an=i;
}
if(!tr[u].idx)tr[u].idx=++pid;
idx=tr[u].idx;
}
queue<int>q;
void build(){
while(!q.empty())q.pop();
for(int i=0;i<2;i++)if(tr[0].son[i])q.push(tr[0].son[i]);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<2;i++){
if(tr[u].son[i]){
tr[tr[u].son[i]].fail=tr[tr[u].fail].son[i];
tr[tr[tr[u].fail].son[i]].du++;
q.push(tr[u].son[i]);
}else tr[u].son[i]=tr[tr[u].fail].son[i];
}
}
for(int i=0;i<=tot;i++){
for(int x=0;x<2;x++){
for(int p=i;;p=tr[p].fail){
if(tr[p].an<n&&x<(s[tr[p].an+1]-'0'))tr[i].sm[x]++;
if(!p)break;
}
}
for(int p=i;p;p=tr[p].fail)if(tr[p].an<n)tr[i].pr++;
}
}
void query(char t[]){
int u=0;
for(int i=1;t[i];i++){
u=tr[u].son[t[i]-'a'];
tr[u].an++;
}
}
}
struct node{
int s,k,u,h;
ull hsh()const{
return ((ull)h<<42)|((ull)u<<32)|((ull)s<<16)|(ull)k;
}
}h,t;
int idx[205];
queue<node>q;
struct chash {
size_t operator()(ull x) const {
x ^= x >> 33;
x *= 0xff51afd7ed558ccdLL;
x ^= x >> 33;
x *= 0xc4ceb9fe1a85ec53LL;
x ^= x >> 33;
return x;
}
};
ull tt;
gp_hash_table<ull,pair<ull,char>,chash>mp;
void print(ull h){
if(h==tt)return;
print(mp[h].first);
printf("%c",mp[h].second);
}
void solve(){
mp.clear();
scanf("%d%d",&n,&k);
scanf("%s",s+1);
AC::init();
AC::insert(s,idx[1]);
AC::build();
while(!q.empty())q.pop();
q.push((node){0,0,0,0});
h={0,0,0,0};
mp[tt=h.hsh()]=make_pair(h.hsh(),'\0');
while(!q.empty()){
h=q.front();
q.pop();
for(int x=0;x<2;x++){
t=h;
t.u=AC::tr[h.u].son[x];
t.s+=AC::tr[h.u].sm[x];
t.k+=t.s+AC::tr[t.u].pr;
if(AC::tr[t.u].an==n)t.h=1;
if(!t.h&&1ll*(n-AC::tr[t.u].an)*t.s+t.k>k)continue;
if(mp.find(t.hsh())!=mp.end()||t.k>k||t.s>k)continue;
mp[t.hsh()]=make_pair(h.hsh(),x+'0');
if(t.h&&t.k==k){
print(t.hsh());
puts("");
return;
}
q.push(t);
}
}
puts("Impossible");
}
int main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%d%d",&T,&T);
while(T--)solve();
return 0;
}