【题解】Luogu P4045 [JSOI2009] 密码
设 \(dp_{i,j,S}\) 表示填了 \(i\) 位,在 AC 自动机上的 \(j\) 号节点,当前覆盖的字符串集位 \(S\) 的方案数。于是有转移:
\[\large{dp_{i,j,S}\to dp_{i+1,tr_{j,k},S\operatorname{or}sta_{tr_{j,k}}}}
\]
其中 \(tr_{j,k}\) 表示 AC 自动机上 \(j\) 点加上字符 \(k\) 的节点,\(sta_j\) 表示以 \(j\) 点为结尾的字符串构成的集合,\(\operatorname{or}\) 表示按位或。
输出方案,先记忆化搜索确定每个状态 \((i,j,S)\) 能否转移到合法状态,再一遍 dfs 输出即可。
#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=(1<<10)+5;
int n,m,tr[105][30],tot;
int fail[105],sta[105];
ll dp[30][105][maxn];
bool vis[30][105][maxn];
bool f[30][105][maxn];
char ans[maxn];
string s;
queue<int> q;
il bool dfs1(int i,int j,int S){
if(vis[i][j][S]){
return f[i][j][S];
}
vis[i][j][S]=1;
if(i==m){
return f[i][j][S]=S==(1<<n)-1;
}
bool &res=f[i][j][S];
for(int k=0;k<=25;k++){
res|=dfs1(i+1,tr[j][k],S|sta[tr[j][k]]);
}
return res;
}
il void dfs2(int i,int j,int S){
if(i==m){
for(int k=1;k<=m;k++){
cout<<ans[k];
}
cout<<"\n";
return ;
}
for(int k=0;k<=25;k++){
if(f[i+1][tr[j][k]][S|sta[tr[j][k]]]){
ans[i+1]=k+'a';
dfs2(i+1,tr[j][k],S|sta[tr[j][k]]);
}
}
}
namespace cplx{
bool end;
il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>m>>n;
for(int i=1,p;i<=n;i++){
cin>>s;
p=0;
for(int j=0,d;j<s.size();j++){
d=s[j]-'a';
if(!tr[p][d]){
tr[p][d]=++tot;
}
p=tr[p][d];
}
sta[p]|=1<<(i-1);
}
for(int i=0;i<=25;i++){
if(tr[0][i]){
q.push(tr[0][i]);
}
}
while(q.size()){
int u=q.front();
q.pop();
for(int i=0;i<=25;i++){
if(tr[u][i]){
fail[tr[u][i]]=tr[fail[u]][i];
sta[tr[u][i]]|=sta[fail[tr[u][i]]];
q.push(tr[u][i]);
}
else{
tr[u][i]=tr[fail[u]][i];
}
}
}
dp[0][0][0]=1;
for(int i=0;i<=m;i++){
for(int j=0;j<=tot;j++){
for(int S=0;S<1<<n;S++){
if(!dp[i][j][S]){
continue;
}
for(int k=0;k<=25;k++){
dp[i+1][tr[j][k]][S|sta[tr[j][k]]]+=dp[i][j][S];
}
}
}
}
ll ans=0;
for(int i=0;i<=tot;i++){
ans+=dp[m][i][(1<<n)-1];
}
cout<<ans<<"\n";
if(ans>42){
return 0;
}
dfs1(0,0,0);
dfs2(0,0,0);
return 0;
}
}
int main(){return asbt::main();}

浙公网安备 33010602011771号