您的位置:首页 > Web前端 > JavaScript

BZOJ1030 [JSOI2007]文本生成器 补全AC自动机+简单DP

2017-12-11 14:19 489 查看

大家都吼强,可与之共勉 。

题意:

  您现在有n个单词,您得构造一只长度为m的文章,使得这个文章里面包含至少一个单词。(所有文本只包含大写字母)问构造方案数,答案对10007取模。

  数据范围n≤60,m≤100。

题解:补集转化,AC自动机上面DP。

  首先我们构造出这n个单词的AC自动机,然后考虑到求出能构造出的,我们可以用总方案数减去不能构造出的方案数。

  不能构造出的就是在自动机走不到单词的尾节点,于是简单DP求出方案数。

复杂度O(m⋅节点数⋅26)。

  补全AC自动机方便死了呢

/**************************************************************
Problem: 1030
User: Lazer2001
Language: C++
Result: Accepted
Time:192 ms
Memory:82372 kb
****************************************************************/

# include <bits/stdc++.h>

# define N 100010

int n, m ;
short dp [6005] [6005] ;

class AhoCrasickAutoMaton  {
private :
int ncnt ;
bool ban
;
int go
[26], fail
;

public :
inline void insert ( char* s )  {
int cur = 0 ;
for ( char *pt = s ; *pt ; ++ pt )  {
if ( ! go [cur] [*pt - 'A'] )  go [cur] [*pt - 'A'] = ++ ncnt ;
cur = go [cur] [*pt - 'A'] ;
}
ban [cur] = 1 ;
}
void build ( )  {
fail [0] = -1 ;
static std :: queue < int > Q ;
for ( int i = 0 ; i < 26 ; ++ i )
if ( go [0] [i] )  Q.push ( go [0] [i] ) ;
while ( ! Q.empty ( ) )  {
int cur = Q.front ( ) ; Q.pop ( ) ;
for ( int i = 0 ; i < 26 ; ++ i )
if ( go [cur] [i] )  {
Q.push ( go [cur] [i] ) ;
fail [go [cur] [i]] = go [fail [cur]] [i] ;
} else  {
go [cur] [i] = go [fail [cur]] [i] ;
}
ban [cur] |= ban [fail [cur]] ;
}
}
int Dp ( )  {
dp [0] [0] = 1 ;
for ( int i = 1 ; i <= m ; ++ i )
for ( int j = 0 ; j <= ncnt ; ++ j )  {
if ( ban [j] )  continue ;
for ( int k = 0 ; k < 26 ; ++ k )  {
dp [i] [go [j] [k]] += dp [i - 1] [j] ;
if ( dp [i] [go [j] [k]] >= 10007 )  dp [i] [go [j] [k]] -= 10007 ;
}
}
int cnt1 = 0, cnt2 = 1 ;
for ( int i = 0 ; i <= ncnt ; ++ i )
if ( ! ban [i] )  {
cnt1 += dp [m] [i] ;
if ( cnt1 >= 10007 )  cnt1 -= 10007 ;
}
for ( int i = 1 ; i <= m ; ++ i )  ( cnt2 *= 26 ) %= 10007 ;
return ( cnt2 - cnt1 + 10007 ) % 10007 ;
}
} T ;

int main ( )  {
scanf ( "%d%d", & n, & m ) ;
while ( n -- )  {
static char s [6005] ;
scanf ( "%s", s ) ;
T.insert ( s ) ;
}
T.build ( ) ;
printf ( "%d\n", T.Dp ( ) ) ;
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: