zoukankan      html  css  js  c++  java
  • 魔法咒语

    魔法咒语

    没有一个点到极限数据海星。。。虽然极限数据好像没法做?

    前 60% 很套路的 acam dp。$ dp[i][j] $ 表示当前匹配到第 $ i $ 个位置,当前在 ACAM 上 $ j $ 号节点。

    后 40% 的数据看起来很矩乘。(其实整个数据范围都挺矩乘的) 由于 $ dp[i][j] $ 只能从 $ dp[i - 1][t] $ 和 $ dp[i - 2][t] $ 转移到,矩阵加速一下就好了。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    #define MAXN 100026
    #define P 1000000007
    int n , m , l; 
    
    int son[MAXN][26] , fail[MAXN] , num[MAXN] , idx;
    void ins( char* ch , int id ) {
    	int len = strlen( ch ) , cur = 0;
    	for( int i = 0 ; i < len ; ++ i ) {
    		int x = ch[i] - 'a';
    		if( !son[cur][x] ) son[cur][x] = ++ idx;
    		cur = son[cur][x];
    	}
    	num[cur] = 1;
    }
    void build( ) {
    	queue<int> Q;
    	for( int i = 0 ; i < 26 ; ++ i ) if( son[0][i] ) 
    		Q.push( son[0][i] );
    	while( !Q.empty() ) {
    		int x = Q.front(); Q.pop();
    		int t = fail[x];
    		for( int i = 0 ; i < 26 ; ++ i ) 
    			if( son[x][i] ) 
    				fail[son[x][i]] = son[fail[x]][i] , Q.push( son[x][i] ) , num[son[x][i]] |= ( num[son[fail[x]][i]] );
    			else
    				son[x][i] = son[fail[x]][i];
    	}
    }
    int dp[106][106] , len[106];
    char ch[106][106] , zh[106];
    
    int N;
    struct mtrx {
    	int A[206][206];
    } cur , tmp , ans ;
    void mul( mtrx& A , mtrx& B) {
    	memset( tmp.A , 0 , sizeof tmp.A );
    	for( int i = 0 ; i < N ; ++ i )
    		for( int k = 0 ; k < N ; ++ k ) if( A.A[i][k] )
    			for( int j = 0 ; j < N ; ++ j ) 
    				( tmp.A[i][j] += 1ll * A.A[i][k] * B.A[k][j] % P ) %= P;
    }
    void power( int n ) {
    	for( int i = 0 ; i < N ; ++ i ) ans.A[i][i] = 1;
    	while( n ) {
    		if( n & 1 ) mul( ans , cur ) , ans = tmp;
    		mul( cur , cur ) , cur = tmp , n >>= 1;
    	}
    }
    
    signed main() {
    	cin >> n >> m >> l;
    	for( int i = 1 ; i <= n ; ++ i ) scanf("%s",ch[i]) , len[i] = strlen( ch[i] );
    	for( int i = 1 ; i <= m ; ++ i ) scanf("%s",zh) , ins( zh , i );
    	build( );
    	if( l <= 100 ) {
    		dp[0][0] = 1;
    		for( int i = 0 ; i < l ; ++ i ) 
    			for( int k = 0 ; k <= idx ; ++ k) {
    				for( int j = 1 ; j <= n ; ++ j ) {
    					if( i + len[j] > l ) continue;
    					int t = k;
    					for( int p = 0 ; p < len[j] ; ++ p ) 
    						if( !num[son[t][ch[j][p] - 'a']] ) t = son[t][ch[j][p] - 'a'];
    						else { t = -1; break; }
    					if( ~t ) ( dp[i + len[j]][t] += dp[i][k] ) %= P;
    				}
    			}
    		int res = 0;
    		for( int i = 0 ; i <= idx ; ++ i )
    			( res += dp[l][i] ) %= P;
    		cout << res << endl;
    	} else {
    		for( int i = idx + 1 ; i <= idx * 2 + 1 ; ++ i ) cur.A[i][i - idx - 1] = 1;
    		for( int i = 0 ; i <= idx ; ++ i ) {
    			for( int j = 1 ; j <= n ; ++ j ) {
    				int t = i;
    				for( int p = 0 ; p < len[j] ; ++ p ) 
    					if( !num[son[t][ch[j][p] - 'a']] ) t = son[t][ch[j][p] - 'a'];
    					else { t = -1; break; }
    				if( ~t ) 
    					if( len[j] == 1 ) ++ cur.A[i][t]; 
    					else ++ cur.A[i][t + idx + 1];
    			}
    		}
    		N = idx * 2 + 2;
    //		for( int i = 0 ; i < N ; ++ i ) {
    //			for( int j = 0 ; j < N ; ++ j ) cout << cur.A[i][j] << ' '; puts("");
    //		}
    		power( l );
    		memset( cur.A , 0 , sizeof cur.A );
    		cur.A[0][0] = 1;
    		mul( cur , ans );
    		int res = 0;
    		for( int i = 0 ; i <= idx ; ++ i ) ( res += tmp.A[0][i] ) %= P;
    		cout << res << endl;
    	}
    }
    
  • 相关阅读:
    Spark RDD简介与运行机制概述
    MongoDB 3.0.6的主,从,仲裁节点搭建
    kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
    Spark配置参数调优
    SparkSQL项目中的应用
    SparkSQL相关语句总结
    Hadoop系统架构
    Hadoop常用命令
    spark单机模式简单搭建
    Spark参数配置说明
  • 原文地址:https://www.cnblogs.com/yijan/p/bzoj4861.html
Copyright © 2011-2022 走看看