bzoj 4416 阶乘字符串 Posted on 2019-07-18 | Edited on 2019-07-19 | Views: 23 状压 dp . 设 f(S) 表示从 1 开始,使得集合 S 中元素所有排列均出现的最小长度. 预处理从位置 i 开始,字母 j 首次出现的位置 nxt(i,j) ,可以状压 dp .转移时枚举排列的最后一个元素的位置, O(2n⋅n+len⋅n) . n≤26 ,似乎过不去?然而字符串长度 ≤450 ,最小的合法串是 O(n2) 级别, n≥22 时一定无解. Copy123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=451,MAXS=(1<<21)+10;int n,nxt[MAXN][26],f[MAXS];char buf[MAXN];void solve(){ n=read(); scanf("%s",buf+1); if(n>=22) { puts("NO"); return; } int m=strlen(buf+1); buf[0]=buf[m+1]='#'; for(int j=0;j<n;++j) nxt[m+1][j]=m+1; for(int i=m;i>=0;--i) for(int j=0;j<n;++j) nxt[i][j]=(buf[i+1]-'a'==j)?i+1:nxt[i+1][j]; memset(f,0,sizeof f); int mx=(1<<n)-1; for(int i=1;i<=mx;++i) { for(int j=0;j<n;++j) if((1<<j)&i) f[i]=max(f[i],nxt[f[i^(1<<j)]][j]); } if(f[mx]<=m) puts("YES"); else puts("NO");}int main(){ int T=read(); while(T--) solve(); return 0;}
Gitalking ...