bzoj 1030

 

dp[i][j] 表示,在AC自动机中,从根节点开始,走了i条边,并且经过的点不包含危险节点,走到了j节点的路径数。

收获:

  1、正难则反

  2、一个字符串不包含给定pattern中的任何一个,则该字符串在AC自动机上走时不会走到“危险节点”。

  3、DFS可以做的事情,可以考虑DP来做。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5 #define fprintf(...)
 6 #define M 10007
 7 #define maxn 6010
 8 using namespace std;
 9 
10 int n, len;
11 int son[maxn][26], fail[maxn], ikey[maxn], ntot;
12 int dp[102][maxn];
13 
14 void insert( const char *P ) {
15     int n=strlen(P);
16     int u=0;
17     for( int i=0; i<n; i++ ) {
18         int c=P[i]-'A';
19         if( !son[u][c] ) son[u][c]=++ntot;
20         fprintf( stderr, "%d->%d %c\n", u, son[u][c], c+'a' );
21         u=son[u][c];
22     }
23     ikey[u] = true;
24 }
25 void build() {
26     queue<int> qu;
27     for( int c=0; c<26; c++ ) {
28         int v=son[0][c];
29         if( !v ) continue;
30         qu.push( v );
31         fail[v] = 0;
32         fprintf( stderr, "fail[%d] = %d\n", v, fail[v] );
33     }
34     while( !qu.empty() ) {
35         int u=qu.front();
36         qu.pop();
37         for( int c=0; c<26; c++ ) {
38             int v=son[u][c];
39             int w=fail[u];
40             if( !v ) {
41                 son[u][c] = son[fail[u]][c];
42                 fprintf( stderr, "%d->%d %c\n", u, son[u][c], c+'a' );
43             } else {
44                 while( w && !son[w][c] ) w=fail[w];
45                 fail[v] = son[w][c];
46                 fprintf( stderr, "fail[%d] = %d\n", v, fail[v] );
47                 ikey[v] |= ikey[fail[v]];
48                 qu.push( v );
49             }
50         }
51     }
52 }
53 void work() {
54     dp[0][0] = 1;
55     for( int i=0; i<=len; i++ ) 
56         for( int u=0; u<=ntot; u++ )
57             if( dp[i][u] ) {
58                 fprintf( stderr, "dp[%d][%d] = %d\n", i, u, dp[i][u] );
59                 for( int c=0; c<26; c++ ) {
60                     int v=son[u][c];
61                     if( ikey[v] ) continue;
62                     dp[i+1][v] += dp[i][u];
63                     if( dp[i+1][v]>=M ) dp[i+1][v]-=M;
64                 }
65             }
66     int ans = 1;
67     for( int i=1; i<=len; i++ )
68         ans = (ans*26)%M;
69     for( int u=0; u<=ntot; u++ ) {
70         ans -= dp[len][u];
71         if( ans<0 ) ans+=M;
72     }
73     printf( "%d\n", ans );
74 }
75 int main() {
76     scanf( "%d%d", &n, &len );
77     for( int i=1; i<=n; i++ ) {
78         char str[110];
79         scanf( "%s", str );
80         insert( str );
81     }
82     build();
83     work();
84 }
View Code

 

posted @ 2015-03-15 15:08  idy002  阅读(220)  评论(0编辑  收藏  举报