• HDOJ 2825 Wireless Password (AC自动机+DP)


    题意:给m个字符串,求长为n且至少包含k个上述字符串的字符串有多少个。

    数据范围:(1<=n<=25),(0<=m<=10)

    分析:用dp[i][cur][s]表示走i步后,到达结点cur,包含的字符串压缩为状态s(第x位为1表示包含第x个字符串)的字符串有多少个。

    TLE:当dp[i-1][pre][s]=0时,直接continue,不用进入下一层循环,经此优化后就AC了。

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    #define NODE 101
    #define MOD 20090717
    
    int n,m,cnt;
    int next[NODE][26],fail[NODE],flag[NODE],node;
    int dp[26][NODE][1<<10];
    
    int newnode()
    {
        fail[node]=flag[node]=0;
        memset(next[node],0,sizeof(next[0]));
        return node++;
    }
    void insert(char *s,int id)
    {
        int i,k,cur;
        for(i=cur=0;s[i];i++)
        {
            k=s[i]-'a';
            if(!next[cur][k])   next[cur][k]=newnode();
            cur=next[cur][k];
        }
        flag[cur] |=(1<<id);
    }
    void makenext()
    {
        int u,v;
        queue<int>q;
    
        q.push(0);
        while(!q.empty())
        {
            u=q.front(),q.pop();
            for(int k=0;k<26;k++)
            {
                v=next[u][k];
                if(v)   q.push(v);
                else    next[u][k]=next[fail[u]][k];
                if(u&&v)
                {
                    fail[v]=next[fail[u]][k];
                    flag[v] |=flag[fail[v]];
                }
            }
        }
    }
    int cal(int s)
    {
        int ret=0;
        while(s)
        {
            ret+=s&1;
            s>>=1;
        }
        return ret;
    }
    void DP()
    {
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<node;j++)
                memset(dp[i][j],0,sizeof(dp[0][0][0])*(1<<m));
        }
        dp[0][0][0]=1;
    
        for(int i=1;i<=n;i++)
        {
            for(int pre=0;pre<node;pre++)
            {
                for(int s=0;s<(1<<m);s++)
                {
                    if(dp[i-1][pre][s]==0)  continue;
                    for(int k=0;k<26;k++)
                    {
                        int cur=next[pre][k];
                        int ns=s | flag[cur];
                        dp[i][cur][ns]+=dp[i-1][pre][s];
                        dp[i][cur][ns]%=MOD;
                    }
                }
            }
        }
        int ans=0;
        for(int cur=0;cur<node;cur++)
        {
            for(int s=0;s<(1<<m);s++)
            {
                if(cal(s)>=cnt)
                {
                    ans+=dp[n][cur][s];
                    ans%=MOD;
                }
            }
        }
        printf("%d\n",ans);
    }
    int main()
    {
        char s[11];
        while(scanf("%d%d%d",&n,&m,&cnt))
        {
            if(!n&&!m&&!cnt)    break;
            node=0,newnode();
            for(int i=0;i<m;i++)
            {
                scanf("%s",s);
                insert(s,i);
            }
            makenext();
            DP();
        }
        return 0;
    }
  • 相关阅读:
    Sobel算子 (转)
    由矩阵运算来看初等矩阵的左乘右乘所影响到矩阵的行列变换的本质(转)
    矩阵的迹(转)
    深度神经网络识别图形图像的基本原理(转)
    图解卷积神经网络(二)(转)
    Matlab 的reshape函数(转)
    iOS关键词weak和assign的区别
    网络层HTPPS和HTTP的概念与区别
    iOS开发之#impor与#include的区别
    iOS制作自己的Framework框架
  • 原文地址:https://www.cnblogs.com/algorithms/p/2667728.html
Copyright © 2020-2023  润新知