11.【题解】密码
题解
题意
- 给你几个字符串,给你密码长度,之后求出密码有多少种可能,其中如果方案数 \(\leq 42\) ,则需要按字典序输出所有方案。
题解
- 首先先求出每两个字符串的最大重合,记为 \(\large rel{_i}{_,}{_j}\) ( \(relation\) ,在枚举时使用。
(其实应该用 \(dfs\) ),但蒟蒻太蒻了,所以用祖传 \(for\) 循环解决 \(qwq\)。将字符串存到 \(Trie\) 中,然后跑一遍 \(fail\) 指针,之后用状压 \(DP\) 先求出方案数。 \(\large dp{_i}{_,}{_j}{_,}{_k}\) 中, \(i\) 是当前节点的状态,也就是当前节点是哪个字母; \(j\) 是当前在哪个节点, \(k\) 是状态,也就是当前包含了那些字符串,用二进制的每一位来表示是否存在。 - 由于需要以字典序输出,所以将所有的解存起来,之后 \(sort\) 一遍输出即可。
代码
代码不具有参考意义 \(qwq\)
#include<bits/stdc++.h>
#define int long long
#define N (1000010)
#define I i
#define Int int
#define sort stable_sort
using namespace std;
namespace IO
{
#define ll long long
const int MAX=1<<24;
char buf[MAX],*p1=buf,*p2=buf;
char obuf[MAX],*o=obuf;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
//template<typename T>
//inline T read()
inline int read()
{
int x=0;bool f=1;
char c=gc();
for(;c<48||c>57;c=gc())if(c=='-')f=0;
for(;c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c^48);
return f?x:~x+1;
}
void print(ll x){if(x>9)print(x/10);*o++=(x%10)+'0';}
void pit(ll x){if(x<0)*o++='-',x=~x+1;print(x);}
void write(ll x,char ed){pit(x);*o++=ed;}
void flush(){fwrite(obuf,o-obuf,1,stdout);}
#undef ll
}
using IO::read;using IO::write;using IO::flush;using std::complex;
inline int min(int x,int y){return y&((y-x)>>31)|x&(~(y-x)>>31);}
inline int max(int x,int y){return x&((y-x)>>31)|y&(~(y-x)>>31);}
inline void swap(int &x,int &y){int tmp=x;x=y;y=tmp;}
long long n,m;
void init_set()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
namespace AC_Auto
{
string de[15];
int rel[15][15];
int cnt;
struct aa
{
int son[27],nxt,ed;
void init(){memset(son,0,sizeof(son)),nxt=ed=0;}
}t[300010];
queue<int>q;
void init()
{
for(int i(0);i<=cnt;++i)t[i].init();
cnt=0;
}
void insert(string d,int id)
{
int u(0),len(d.size());
for(int i(0);i<len;++i)
{
int v(d[i]-'a');
if(!t[u].son[v])t[u].son[v]=++cnt;
u=t[u].son[v];
}
t[u].ed=(1<<(id-1));
return;
}
void nxt_set()
{
for(int i(0);i<26;++i)if(t[0].son[i])q.push(t[0].son[i]);
for(;q.size();)
{
int u(q.front());q.pop();
int Nxt(t[u].nxt);
for(int i(0);i<26;++i)
{
int v(t[u].son[i]);
if(!v){t[u].son[i]=t[Nxt].son[i];continue;}
t[v].nxt=t[Nxt].son[i];
t[v].ed|=t[t[v].nxt].ed;
//假如失配指针是个终止节点,
//由于失配指针的前缀与当前字符串后缀相同,
//所以实际上另一个字符串已经结束了。
q.push(v);
}
}
}
void solve(signed x,signed y)
{
int lx(de[x].size());
for(signed i(0);i<lx;++i)
{
bool ret=true;
for(signed j(i);j<lx;++j)
{
if(de[y][j-i]^de[x][j])
{ret=false;break;}
}
if(ret)//这时就是最优解了。
{rel[x][y]=lx-i;return;}
}
rel[x][y]=0;
}
}
using namespace AC_Auto;
int dp[26][260][1030];
int a[15],fontanie,tp;
string las[50];
signed main()
{
init_set();
cin>>m>>n;
for(int i(1);i<=n;++i)cin>>de[i],insert(de[i],i);
nxt_set();
for(signed i(1);i<=n;++i)
for(signed j(1);j<=n;++j)
if(i^j)solve(i,j);
dp[0][0][0]=1;
for(int i(1);i<=m;++i)
for(int j(0);j<=cnt;++j)
for(int l(0);l<(1<<n);++l)
if(dp[i-1][j][l])
for(int k(0);k<26;++k)
dp[i][t[j].son[k]][l|t[t[j].son[k]].ed]+=dp[i-1][j][l];
for(int i(0);i<=cnt;++i)
fontanie+=dp[m][i][(1<<n)-1];
cout<<fontanie<<'\n';
if(fontanie>42)exit(0);
switch(n)
{
case 1:
cout<<de[1];
break;
case 2:
for(int i1(1);i1<=n;++i1)
{
for(int i2(1);i2<=n;++i2)
{
if(i1!=i2)
{
if(de[i1].size()+de[i2].size()-rel[i1][i2]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
las[tp]+='\n';
}
}
}
break;
case 3:
for(int i1(1);i1<=n;++i1)
{
for(int i2(1);i2<=n;++i2)
{
if(i1!=i2)
{
for(int i3(1);i3<=n;++i3)
{
if(i1!=i3&&i2!=i3)
{
if(de[i1].size()+de[i2].size()+de[i3].size()-rel[i1][i2]-rel[i2][i3]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
las[tp]+='\n';
}
}
}
}
}
break;
case 4:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
las[tp]+='\n';
}
break;
case 5:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
las[tp]+='\n';
}
break;
case 6:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
for(int i6(1);i6<=n;++i6)
if(i1!=i6&&i2!=i6&&i3!=i6&&i4!=i6&&i5!=i6)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()+de[i6].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]-rel[i5][i6]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
for(int l(rel[i5][i6]);l<de[i6].size();++l)
las[tp]+=de[i6][l];
las[tp]+='\n';
}
break;
case 7:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
for(int i6(1);i6<=n;++i6)
if(i1!=i6&&i2!=i6&&i3!=i6&&i4!=i6&&i5!=i6)
for(int i7(1);i7<=n;++i7)
if(i1!=i7&&i2!=i7&&i3!=i7&&i4!=i7&&i5!=i7&&i6!=i7)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()+de[i6].size()+de[i7].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]-rel[i5][i6]-rel[i6][i7]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
for(int l(rel[i5][i6]);l<de[i6].size();++l)
las[tp]+=de[i6][l];
for(int l(rel[i6][i7]);l<de[i7].size();++l)
las[tp]+=de[i7][l];
las[tp]+='\n';
}
break;
case 8:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
for(int i6(1);i6<=n;++i6)
if(i1!=i6&&i2!=i6&&i3!=i6&&i4!=i6&&i5!=i6)
for(int i7(1);i7<=n;++i7)
if(i1!=i7&&i2!=i7&&i3!=i7&&i4!=i7&&i5!=i7&&i6!=i7)
for(int i8(1);i8<=n;++i8)
if(i1!=i8&&i2!=i8&&i3!=i8&&i4!=i8&&i5!=i8&&i6!=i8&&i7!=i8)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()+de[i6].size()+de[i7].size()+de[i8].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]-rel[i5][i6]-rel[i6][i7]-rel[i7][i8]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
for(int l(rel[i5][i6]);l<de[i6].size();++l)
las[tp]+=de[i6][l];
for(int l(rel[i6][i7]);l<de[i7].size();++l)
las[tp]+=de[i7][l];
for(int l(rel[i7][i8]);l<de[i8].size();++l)
las[tp]+=de[i8][l];
las[tp]+='\n';
}
break;
case 9:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
for(int i6(1);i6<=n;++i6)
if(i1!=i6&&i2!=i6&&i3!=i6&&i4!=i6&&i5!=i6)
for(int i7(1);i7<=n;++i7)
if(i1!=i7&&i2!=i7&&i3!=i7&&i4!=i7&&i5!=i7&&i6!=i7)
for(int i8(1);i8<=n;++i8)
if(i1!=i8&&i2!=i8&&i3!=i8&&i4!=i8&&i5!=i8&&i6!=i8&&i7!=i8)
for(int i9(1);i9<=n;++i9)
if(i1!=i9&&i2!=i9&&i3!=i9&&i4!=i9&&i5!=i9&&i6!=i9&&i7!=i9&&i8!=i9)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()+de[i6].size()+de[i7].size()+de[i8].size()+de[i9].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]-rel[i5][i6]-rel[i6][i7]-rel[i7][i8]-rel[i8][i9]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
for(int l(rel[i5][i6]);l<de[i6].size();++l)
las[tp]+=de[i6][l];
for(int l(rel[i6][i7]);l<de[i7].size();++l)
las[tp]+=de[i7][l];
for(int l(rel[i7][i8]);l<de[i8].size();++l)
las[tp]+=de[i8][l];
for(int l(rel[i8][i9]);l<de[i9].size();++l)
las[tp]+=de[i9][l];
las[tp]+='\n';
}
break;
case 10:
for(int i1(1);i1<=n;++i1)
for(int i2(1);i2<=n;++i2)
if(i1!=i2)
for(int i3(1);i3<=n;++i3)
if(i1!=i3&&i2!=i3)
for(int i4(1);i4<=n;++i4)
if(i1!=i4&&i2!=i4&&i3!=i4)
for(int i5(1);i5<=n;++i5)
if(i1!=i5&&i2!=i5&&i3!=i5&&i4!=i5)
for(int i6(1);i6<=n;++i6)
if(i1!=i6&&i2!=i6&&i3!=i6&&i4!=i6&&i5!=i6)
for(int i7(1);i7<=n;++i7)
if(i1!=i7&&i2!=i7&&i3!=i7&&i4!=i7&&i5!=i7&&i6!=i7)
for(int i8(1);i8<=n;++i8)
if(i1!=i8&&i2!=i8&&i3!=i8&&i4!=i8&&i5!=i8&&i6!=i8&&i7!=i8)
for(int i9(1);i9<=n;++i9)
if(i1!=i9&&i2!=i9&&i3!=i9&&i4!=i9&&i5!=i9&&i6!=i9&&i7!=i9&&i8!=i9)
for(int i10(1);i10<=n;++i10)
if(i1!=i10&&i2!=i10&&i3!=i10&&i4!=i10&&i5!=i10&&i6!=i10&&i7!=i10&&i8!=i10&&i9!=i10)
{
if(de[i1].size()+de[i2].size()+de[i3].size()+de[i4].size()+de[i5].size()+de[i6].size()+de[i7].size()+de[i8].size()+de[i9].size()+de[i10].size()-rel[i1][i2]-rel[i2][i3]-rel[i3][i4]-rel[i4][i5]-rel[i5][i6]-rel[i6][i7]-rel[i7][i8]-rel[i8][i9]-rel[i9][i10]!=m)continue;
++tp;
for(int l(0);l<de[i1].size();++l)
las[tp]+=de[i1][l];
for(int l(rel[i1][i2]);l<de[i2].size();++l)
las[tp]+=de[i2][l];
for(int l(rel[i2][i3]);l<de[i3].size();++l)
las[tp]+=de[i3][l];
for(int l(rel[i3][i4]);l<de[i4].size();++l)
las[tp]+=de[i4][l];
for(int l(rel[i4][i5]);l<de[i5].size();++l)
las[tp]+=de[i5][l];
for(int l(rel[i5][i6]);l<de[i6].size();++l)
las[tp]+=de[i6][l];
for(int l(rel[i6][i7]);l<de[i7].size();++l)
las[tp]+=de[i7][l];
for(int l(rel[i7][i8]);l<de[i8].size();++l)
las[tp]+=de[i8][l];
for(int l(rel[i8][i9]);l<de[i9].size();++l)
las[tp]+=de[i9][l];
for(int l(rel[i9][i10]);l<de[i10].size();++l)
las[tp]+=de[i10][l];
las[tp]+='\n';
}
break;
}
sort(las+1,las+1+tp);
for(int i(1);i<=tp;++i)
cout<<las[i];
return 0;
}