11.【题解】密码

密码

hzoi

题解

题意

  • 给你几个字符串,给你密码长度,之后求出密码有多少种可能,其中如果方案数 \(\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;
}
posted @ 2024-02-18 14:38  minecraft114514  阅读(28)  评论(1编辑  收藏  举报