poj1625 Censored!

poj1625 Censored!

题目大意:给出n个模式串,问长为m的不包含任何一个模式串的字符串有多少个

dp[i][j]表示长度为i,走到j号节点的种数。要用大数,插入时,把asscil码都加上128,避免负值

自己整理的大数模版很挫,可以忽略

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<queue>
#include<string.h>
using namespace std ;

const int maxn = 1000 ;
int max ( int a , int b ) { return a > b ? a : b ; }

struct bign
{
    short s[maxn] , len ;
    bign () { memset ( s ,0 , sizeof ( s ) ) ; len = 1 ; }
    bign operator = ( const char *num)
    {
        len = strlen ( num ) ;
        for ( int i = 0 ; i < len ; i ++ ) s[i] = num[len-i-1] - '0' ;
        return *this ;
    }
    bool operator < ( const bign &b ) const
    {
        if ( len != b.len ) return len < b.len ;
        for ( int i = len - 1 ; i >= 0 ; i -- )
            if ( s[i] != b.s[i] ) return s[i] < b.s[i] ;
        return false ;
    }
    bool operator > ( const bign &b ) const { return b < *this ; }
    bool operator <= ( const bign &b ) const { return !( b < *this ) ; }
    bool operator >= ( const bign &b ) const { return !( *this < b ) ; }
    bool operator != ( const bign &b ) const { return ( *this < b ) || ( b < *this ) ; }
    bool operator == ( const bign &b ) const { return !( *this < b ) && !( b < *this ) ; }
    bign operator = ( int num )
    {
        char s[maxn] ;
        sprintf ( s , "%d" , num ) ;
        *this = s ;
        return *this ;
    }
    bign ( const char *num ) { *this = num ; }
    bign ( int num ) { *this = num ; }
    string str () const
    {
        string res ;
        res = "" ;
        for ( int i = 0 ; i < len ; i ++ ) res = ( char ) ( s[i] + '0' ) + res ;
        if ( res == "" ) res = '0' ;
        return res ;
    }
    bign operator + ( const bign& b ) const
    {
        bign c ;
        c.len = 0 ;
        for ( int i = 0 , g = 0 ; g || i < max ( len , b.len ) ; i ++ )
        {
            int x = g ;
            if ( i < len ) x += s[i] ;
            if ( i < b.len ) x += b.s[i] ;
            c.s[c.len++] = x % 10 ;
            g = x / 10 ;
        }
        return c ;
    }
    bign operator += ( const bign& b )
    {
        *this = *this + b ;
        return *this ;
    }
    bign operator - ( const bign& b ) const
    {
        bign t1 , t2 ;
        bign t3 ;
        t3.len = 0 ;
        if ( *this < b ) t1 = b , t2 = *this  ;
        else t1 = *this , t2 = b ;
        for ( int i = 0 ; i < t2.len ; i ++ )
        {
            int g = t1.s[i] - t2.s[i] ;
            if ( g < 0 )
            {
                g += 10 ;
                int j = i ;
                while ( t1.s[j+1] == 0 ) t1.s[j+1] = 9 , j ++ ;
                t1.s[j+1] -- ;
            }
            t3.s[t3.len++] = g ;
        }
        for ( int i = t2.len ; i < t1.len ; i ++ ) t3.s[t3.len++] = t1.s[i] ;
        for ( int i = t3.len - 1 ; i >= 0 ; i -- )
            if ( t3.s[i] == 0 ) t3.len -- ;
            else break ;
        return t3 ;
    }
    bign operator -= ( const bign& b )
    {
        *this = *this - b ;
        return *this ;
    }
    bign operator * ( const bign& b ) const
    {
        bign d ;
        d.len = 0 ;
        for ( int i = 0 ; i < len ; i ++ )
        {
            bign c ;
            c.len = 0 ;
            for ( int k = 0 ; k < i ; k ++ )
                c.s[c.len++] = 0 ;
            for ( int j = 0 , g = 0 ; g || j < b.len ; j ++ )
            {
                if ( j < b.len ) g += s[i]* b.s[j];
                c.s[c.len++] = g % 10 ;
                g = g/10 ;
            }
            d += c ;
        }
        for ( int i = d.len - 1 ; i >= 0 ; i -- )
            if ( d.s[i] == 0 ) d.len -- ;
            else break ;
        if ( d.len == 0 ) d = 0 ;
        return d ;
    }
    bign operator *= ( const bign &b )
    {
        *this = *this * b ;
        return *this ;
    }
    bign operator / ( const bign &b ) const
    {
        if ( *this < b ) return 0 ;
        bign t1 = *this ;
        bign t2 = b ;
        bign c = 10 ;
        bign ans ;
        ans.len = 0 ;
        int j ;
        while ( t1 > t2 )
        {
            bign t3 ; t3 = 0 ;
            for ( int i = t1.len - 1 ; i >= 0 ; i -- )
            {
                t3 *= c ; t3.s[0] = t1.s[i] ;
                if ( t3 >= t2 ) { j = i ; break ; }
            }
            bign x , y , z ;
            for ( int i = 1 ; i <= 9 ; i ++ )
            {
                x = i ;
                y = i + 1 ;
                if ( t2 * i <= t3 && t2 * y > t3 )
                {
                    ans.s[ans.len++] = i ;
                    break ;
                }
            }
            z = t2 * x ;
            z = t3 - z ;
            while ( z < t2 && j > 0 )
            {
                z *= c ;
                z.s[0] = t1.s[--j] ;
                if ( z < t2 )
                ans.s[ans.len++] = 0 ;
            }
            if ( j >= 0 )
            {
                y.len = 0 ;
                for ( int i = 0 ; i < j ; i ++ )
                {
                    z *= c ;
                    y.s[y.len++] = t1.s[i] ;
                }
                z += y ;
            }
            t1 = z ;
        }
        reverse ( ans.s , ans.s + ans.len ) ;
        return ans ;
    }
};

istream& operator >> ( istream &in , bign& x )
{
    string s ;
    in >> s ;
    x = s.c_str() ;
    return in ;
}

ostream& operator << ( ostream &out , const bign &x )
{
    out << x.str() ;
    return out ;
}

int n , m , t ;
bign dp[3][111] ;

char s[maxn] , s1[maxn] ;

class ACauto
{
private :
	int tot ;
	int fail[maxn] ;
	int c[505][maxn] ;
	int id[maxn] ;
	queue<int> Q ;
public :

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

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

	void insert ( char *s )
	{
		int now = 0 ;
		for ( ; *s ; s ++ )
		{
			int k = *s ;
			k += 135 ;
			if ( !c[k][now] ) c[k][now] = new_node () ;
			now = c[k][now] ;
		}
		id[now] = 1 ;
		t = tot ;
	}

	void get_fail ()
	{
		int i , j ;
		int u = 0 ;
		for ( i = 0 ; i < 505 ; i ++ ) if ( c[i][u] ) Q.push ( c[i][u] ) ;
		while ( !Q.empty () )
		{
			u = Q.front () ;
			Q.pop () ;
			for ( i = 0 ; i < 505 ; 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] , Q.push ( e ) ;
				id[e] |= id[fail[e]] ;
			}
		}
	}
	
	void work ()
	{
		int i , j , k ;
		int e , v ;
		for ( i = 0 ; i < m ; i ++ )
		{
			for ( j = 0 ; j < tot ; j ++ )
				for ( k = 0 ; k < n ; k ++ )
				{
					v = s[k] + 135 ;
					e = c[v][j] ;
					if ( id[e] ) continue ;
					int p = j ;
					dp[2][e] += dp[1][j] ;
				}
			for ( j = 0 ; j < tot ; j ++ )
			{
				dp[1][j] = dp[2][j] ;
				dp[2][j] = 0 ;
            }
		}
    }

} ac ;

int main ()
{
	int i , j , k ;
	while ( scanf ( "%d%d%d" , &n , &m , &k ) != EOF )
	{
		ac.init () ;
		getchar () ;
		gets ( s ) ;
		for ( i = 1 ; i <= k ; i ++ )
		{
		    gets ( s1 ) ;
			ac.insert ( s1 ) ;
		}
		ac.get_fail () ;
			for ( j = 0 ; j < t ; j ++ )
				dp[0][j] = dp[1][j] = dp[2][j] = 0 ;
		dp[1][0] = 1 ;
		bign ans ;
        ans = 0 ;
		ac.work () ;
		for ( i = 0 ; i < t ; i ++ )
        {
            ans += dp[1][i] ;
        }
		cout << ans << endl ;
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值