【一道不知道名字的题】AC自动机+dp
来源:互联网 发布:java多线程输出1到100 编辑:程序博客网 时间:2024/06/05 17:54
太懒了,好久没写题解了。
Time Limit : 3000/3000ms (Java/Other) Memory Limit : 65535/65536K (Java/Other)
Total Submission(s) : 34 Accepted Submission(s) : 8
Problem Description
Let Str be a long string and s1,s2,...,sm——collection of short string(s). Let us say that the collection filters Str iff Str can be covered with the string from the collection. Certainly, substrings corresponding to the different positions of the string may intersect or even cover each other. More formally: denote by |Str| the length of Str, let symbols of Str be numbered from 1 to |Str|. Then for each position i in Str there exist pair of indices l, r (1 <= l <= i <= r <= |Str|) such that the substring Str[l ... r] equals one of the elements s1,s2,...,sm of the collection.
Now you are asked to calculate the number of different string of length n filtered by the collection {si}.
As the answer may appear very large, so output it modulo 10007.
For example, a collection of {"cat","tact"} can create 2 strings with length 6 like "catcat" or "catact", and no more.
Now you are asked to calculate the number of different string of length n filtered by the collection {si}.
As the answer may appear very large, so output it modulo 10007.
For example, a collection of {"cat","tact"} can create 2 strings with length 6 like "catcat" or "catact", and no more.
Input
First line contains two integer numbers n and m (1 <= 1000,1<=m<=10) — the length of the defined string and the number of string(s) in the collection correspondently.
Next m lines contain the collection string si, one per line. Each si is a nonempty string of length not greater than 10. The collection may contain identical strings. All the strings consist of lowercase letters only.
Next m lines contain the collection string si, one per line. Each si is a nonempty string of length not greater than 10. The collection may contain identical strings. All the strings consist of lowercase letters only.
Output
Output should contain a single integer — the number of strings filtered by the collection modulo 10007.
Sample Input
2 1a6 2cat tact
Sample Output
12
题目分析:
题意是让你构造一个长度为n的串,使得这个串中的每个字母都属于至少一个子串(即在这个子串中)。首先很明确的是,这个串中不可能有除了给定单词中出现的字母外的字母。考虑到这类构造串的问题大部分和AC自动机有关,于是可以从AC自动机的角度思考。
将给定的m个串插入字典树,然后建立自动机,自动机中每个节点保存以这个节点i为一个串的终点时串的最长长度lens[i]。
然后下面的过程考虑dp,设dp[i][j][k]表示已经处理到第i位,当前状态为ac自动机的节点j,未匹配的长度为k,枚举能转移到的节点nxt(不能转移到自动机的根,如果转移到根就说明出现了没有出现过的字母,这是不行的),则接下来有两种转移:
dp[i + 1][nxt][k + 1] += dp[i][j][k] lens[nxt] <= k
dp[i + 1][nxt][0] += dp[i][j][k] lens[nxt] > k
我们用k=0表示完全被覆盖。
最后我们只要加上所有的i=n,k=0的状态:ans += dp[n][j][0] (0 < j < 自动机节点数)
不好意思我不知道题目在哪,这是训练赛的题^_^
本题 目的就是提供一个解题思路~
代码如下:
#include <stdio.h>#include <cstring>#include <map>#include <algorithm>using namespace std ;typedef long long LL ;#define rep( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 105 ;const int mod = 10007 ;const int W = 26 ;struct Node {Node* next[W] ;Node* fail ;int end ;void init () {rep ( i , 0 , W ) next[i] = NULL ;fail = NULL ;end = 0 ;}} ;struct AC_automation {Node node[MAXN] ;Node* cur ;Node* root ;Node* Q[MAXN] ;int head , tail ;int dp[1005][MAXN][12] ;void init () {cur = node ;root = newnode () ;}Node* newnode () {cur->init () ;return cur ++ ;}void insert ( char s[] , int n ) {Node* now = root ;rep ( i , 0 , n ) {int x = s[i] - 'a' ;if ( now->next[x] == NULL ) now->next[x] = newnode () ;now = now->next[x] ;}now->end = n ;}void build () {root->fail = root ;head = tail = 0 ;rep ( i , 0 , W ) {if ( root->next[i] == NULL ) {root->next[i] = root ;} else {root->next[i]->fail = root ;Q[tail ++] = root->next[i] ;}}while ( head != tail ) {Node* now = Q[head ++] ;now->end = max ( now->end , now->fail->end ) ;rep ( i , 0 , W ) {if ( now->next[i] == NULL ) {now->next[i] = now->fail->next[i] ;} else {now->next[i]->fail = now->fail->next[i] ;Q[tail ++] = now->next[i] ;}}}}void add ( int& x , int y ) {x += y ;if ( x >= mod ) x %= mod ;}void solve ( int n ) {int m = cur - root ;clr ( dp , 0 ) ;dp[0][0][0] = 1 ;For ( i , 1 , n ) {rep ( j , 0 , m ) {rep ( k , 0 , 10 ) if ( dp[i - 1][j][k] ) {rep ( w , 0 , W ) {int nxt = node[j].next[w] - root ;if ( !nxt ) continue ;if ( node[nxt].end < k + 1 ) add ( dp[i][nxt][k + 1] , dp[i - 1][j][k] ) ;else add ( dp[i][nxt][0] , dp[i - 1][j][k] ) ;}}}}int ans = 0 ;rep ( i , 0 , m ) add ( ans , dp[n][i][0] ) ;printf ( "%d\n" , ans ) ;}} ;AC_automation ac ;char s[MAXN] ;int n , m ;void solve () {ac.init () ;rep ( i , 0 , m ) {scanf ( "%s" , s ) ;int len = strlen ( s ) ;ac.insert ( s , len ) ;}ac.build () ;ac.solve ( n ) ;}int main () {while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;return 0 ;}
0 0
- 【一道不知道名字的题】AC自动机+dp
- POJ3691 - AC自动机的第一道DP
- POJ3691 第一道AC自动机+DP 指针版+总结
- 不知道名字的某题_20160622_1
- 不知道名字的某题_20160622_2
- HAPPY!终于独立AC了一道DP的题。。
- poj 1625 AC自动机上的DP
- 关于AC自动机与DP的总结
- 第一次看AC自动机上的dp
- 基因的庇护 (AC自动机 dp)
- 空罐 AC自动机 + DP 好题
- hdu4758 AC自动机+dp
- AC自动机 + DP小结
- AC自动机+DP+hdu2296
- hdu2457 AC自动机+DP
- hdu2296(AC自动机+DP)
- hdu2296 AC自动机+DP
- uvalive4842(AC自动机+DP)
- 清除安卓应用里多余的资源文件
- Java并发编程:Callable、Future和FutureTask
- 分享一个自己写的cnBeta客户端源码
- 1.8
- eclipse查看类的继承、实现关系快捷键
- 【一道不知道名字的题】AC自动机+dp
- 1.9
- Android组件ListView的适配器BaseAdapter
- Leetcode:Binary Search Tree Iterator
- CSU1115 最短的名字
- 线性表实现之一:数组
- PHP Native Interface (PNI)
- vc++ 使用64位平台编译,运行程序出现0xc000007b错误的解决方案
- 1.10