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

[BZOJ1030]-[JSOI2007]文本生成器-AC自动机+dp

2017-12-15 14:21 363 查看

说在前面

并没有什么好说的,但是要保持格式=w=

题目

BZOJ1030传送门

题面太长了,直接贴过来会很丑,刚睡完午觉Izumi表示并不想概括题面…

(这道题并不是权限题,可以直接进去看)

解法

如果先做了BZOJ3530再来看这道题就比较简单了(把3530代码里dfs的限制去掉,直接dfs就是这道题)

至少包含一个 = 所有 减去 一个都不包含

总数很好算,就是26的长度次方。一个都不包含的方案数就是老套路了,对所有字符串建补全AC自动机,对所有字符串结尾节点打上ban标记,并且把标记沿着fail和child边下传,dp的时候不经过这些ban标记的点即可

下面是自带大常数的代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int mmod = 10007 ;
char a[1205] , ss[1505] ;
int N , M , AC_cnt , ss_cnt , dp[155][6505] ;
struct Node{
int id , num ;
bool ban ;
Node *fail , *ch[26] ;
}*root , *arc[10505] ;

void newNode( Node *&nd ){
nd = new Node() ;
nd->id = ++AC_cnt , arc[AC_cnt] = nd ;
nd->fail = NULL , nd->ban = false ;
memset( nd->ch , 0 , sizeof( nd->ch ) ) ;
}

void Insert( char *ts ){
int len = strlen( ts ) ;
Node *nd = root ;
for( int i = 0 ; i < len ; i ++ ){
int nxt = ts[i] - 'A' ;
if( !nd->ch[nxt] ) newNode( nd->ch[nxt] ) ;
nd = nd->ch[nxt] ;
}
nd->ban = true ;
}

queue<Node*> que ;
void getFail(){
que.push( root ) ;
while( !que.empty() ){
Node *u = que.front() ; que.pop() ;
for( int i = 0 ; i < 26 ; i ++ ){
Node *&v = u->ch[i] , *p = u->fail ;
while( p && !p->ch[i] ) p = p->ch[i] ;
if( v ){
v->fail = ( p ? p->ch[i] : root ) ;
v->ban |= ( v->fail->ban | u->ban ) ;//fail或者fa有标记,当前点也应有
que.push( v ) ;
} else v = ( p ? p->ch[i] : root ) ;
}
}
}

int dfs( int len , int AC_id ){
Node *u = arc[AC_id] ;
if( u->ban ) return 0 ;
if( len == M ) return 1 ;
if( dp[len][AC_id] != -1 ) return dp[len][AC_id] ;

int rt = 0 ;
for( int i = 0 ; i < 26 ; i ++ )
rt = ( rt + dfs( len + 1 , u->ch[i]->id ) )%mmod ;
dp[len][AC_id] = rt ;
return rt ;
}

void solve(){
getFail() ;
memset( dp , -1 , sizeof( dp ) ) ;
int ans = 1 , tmp = dfs( 0 , 1 ) ;
for( int i = 1 ; i <= M ; i ++ )
ans = ans * 26%mmod ;
printf( "%d" , ( ans - tmp + mmod )%mmod ) ;
}

int main(){
newNode( root ) ;
scanf( "%d%d" , &N , &M ) ;
for( int i = 1 ; i <= N ; i ++ ){
scanf( "%s" , ss ) ;
Insert( ss ) ;
}
solve() ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: