现在的位置: 首页 > 综合 > 正文

hdu2825 Wireless Password

2013年02月10日 ⁄ 综合 ⁄ 共 2112字 ⁄ 字号 评论关闭
文章目录

hdu2825 Wireless Password

大致题意是:包含下面n个单词中至少m个的长为k个的字符串有几个,n<=25,m<=10,单词的长度也小于时。因为m的范围较小,很容易想到状态压缩dp。

dp[i][j][k]表示长度为i,走到j号节点,状态为k的种数。我是用广搜搜出来的

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std ;
const int mod = 20090717 ;

int dp[27][111][1025] ;

struct Point
{
    int p , step , v ;
} ;
struct Que
{
    int tail , head ;
    Point q[1000005] ;
    void init ()
    {
        head = 1 , tail = 0 ;
    }
    bool empty ()
    {
        return head > tail ;
    }

    Point front ()
    {
        return q[head] ;
    }
    void pop ()
    {
        head = head + 1 ;
    }
    void push ( Point x )
    {
        tail = tail + 1 ;
        q[tail] = x ;
    }
} Q ;

int vis[27][111][1025] ;
int f[3222] ;
class AC_auto
{
private :
    int c[26][111] ;
    int id[111] ;
    int fail[111] ;
    int tot ;
    queue<int> Q1 ;
public :

    int new_node ()
    {
        int i ;
        for ( i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ;
        id[tot] = 0 ;
        fail[tot] = 0 ;
        return tot ++ ;
    }

    void init ()
    {
        tot = 0 ; Q.init () ; while ( !Q1.empty () ) Q1.pop () ; new_node () ;
    }

    void insert ( char *s , int pos )
    {
        int now = 0 ;
        for ( ; *s ; s ++ )
        {
            int k = *s - 'a' ;
            if ( !c[k][now] ) c[k][now] = new_node () ;
            now = c[k][now] ;
        }
        id[now] = 1 << pos ;
    }

    void get_fail ()
    {
        int i , j , u = 0 ;
        for ( i = 0 ; i < 26 ; i ++ ) if ( c[i][u] ) Q1.push ( c[i][u] ) ;
        while ( !Q1.empty () )
        {
            u = Q1.front () ;
            Q1.pop () ;
            for ( i = 0 ; i < 26 ; i ++ )
            {
                if ( !c[i][u] )
                {
                    c[i][u] = c[i][fail[u]] ;
                    continue ;
                }
                int e = c[i][u] ;
                j = fail[u] ;
                while ( j && !c[i][j] ) j = fail[j] ;
                fail[e] = c[i][j] ;
                Q1.push ( e ) ;
                id[e] |= id[fail[e]] ;
            }
        }
    }

    void bfs ( Point u , int n , int m )
    {
        int i , j ;
        Point e ;
        Q.push ( u ) ;
        while ( !Q.empty () )
        {
            u = Q.front () ;
            Q.pop () ;
            vis[u.step][u.v][u.p] = 0 ;
            if ( u.step == n ) return ;
            e.step = u.step + 1 ;
            for ( i = 0 ; i < 26 ; i ++ )
            {
                int k = c[i][u.v] ;
                e.v = k ;
                if ( !id[k] ) e.p = u.p ;
                else e.p = u.p | id[k] ;
                dp[e.step][k][e.p] += dp[u.step][u.v][u.p] ;
                if ( dp[e.step][k][e.p] >= mod ) dp[e.step][k][e.p] -= mod ;
                if ( !vis[e.step][k][e.p] )
                {
                    Q.push ( e ) ;
                    vis[e.step][k][e.p] = 1 ;
                }
            }
        }
    }

    int work ( int n , int m , int l )
    {
        int i , j , k , t ;
        int N = 1 << ( m  ) ;

        for ( j = 0 ; j < N ; j ++ )
            for ( i = 0 ; i < tot ; i ++ )
                for ( k = 0 ; k <= n ; k ++ )
                    dp[k][i][j] = vis[k][i][j] = 0 ;
        dp[0][0][0] = vis[0][0][0] = 1 ;
        Point u ;
        u.step = 0 , u.p = 0 , u.v = 0 ;
        bfs ( u , n , m ) ;
        int ret = 0 ; 
         
        for ( i = 0 ; i < N ; i ++ )
        {
            if ( f[i] < l ) continue ;
            for ( j = 0 ; j < tot ; j ++ )
            {
                ret += dp[n][j][i] ;
                if ( ret >= mod ) ret -= mod ;
            }
        }
        return ret ;
    }

} ac ;

int main ()
{
    int i , j , n , m , l ;
    char s[15] ;
    for ( i = 0 ; i < ( 1 << 10 ) ; i ++ )
    {
        n = 0 ;
        for ( j = 0 ; j < 10 ; j ++ ) if ( i & ( 1 << j ) ) n ++ ;
        f[i] = n ;
    }
    while ( scanf ( "%d%d%d" , &n , &m , &l ) != EOF )
    {
        if ( n == 0 && m == 0 && l == 0 ) break ;
        ac.init () ;
        for ( i = 0 ; i < m ; i ++ )
        {
            scanf ( "%s" , s ) ;
            ac.insert ( s , i ) ;
        }
        ac.get_fail () ;
        printf ( "%d\n" , ac.work ( n , m , l ) ) ;
    }
    return 0 ;
}

抱歉!评论已关闭.