题目大意:给出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 ;
}
}