zoukankan      html  css  js  c++  java
  • Passwords Gym

    Problem E: Passwords

    [Time Limit: 1 s quad Memory Limit: 256 MiB ]

    题意

    给出两个正整数(A,B),再给出(n)个字符串,然后问你满足条件的字符串有多少种,最后答案(\%1e6+3)。条件如下

    [egin{aligned} 1、&长度在A到B之间\ 2、&所有子串不存在n个字符串中任意一个\ 3、&模式串中,把0看成o,1看成i,3看成e,5看成s,7看成t\ 4、&至少存在一个小写字母,一个大写字母,一个数字 end{aligned} ]

    要注意一下题目中的Additionally, for the purposes of avoiding the blacklist, you cannot use (l33t).这句话,我一开始还以为(l33t)也算第(n+1)个字符串,也不能计数,结果发现读错了,这句话只是引出后面那么限制条件。

    思路

    很显然这种在多个字符串上跳来跳去的,然后给出一些限制条件,在(AC自动机)(DP)大部分情况下是(ok)的,而且对(fail)指针(build)时,也很常见,补全成(Trie)图,把(fail[u])的信息传给(u)就可以了。
    那么如何(dp)呢,用(dp[state][i][j])(state)最大为(7),第一位为小写字母,第二问为大写字母,第三次为数字,状压状态,(i)表示匹配串已经到了第(i)位,(j)表示在(AC自动机)上的状态,然后状态就很容易得到了。

    [egin{aligned} dp[st][i][j] &-> dp[st|1][i+1][k] 小写字母时\ dp[st][i][j] &-> dp[st|2][i+1][k] 大写字母时\ dp[st][i][j] &-> dp[st|4][i+1][k] 数字时\ end{aligned} ]

    最后输出(dp[7][sum_A^B][sum_1^{sz}])就可以了。

    /***************************************************************
        > File Name    : E.cpp
        > Author       : Jiaaaaaaaqi
        > Created Time : 2019年05月08日 星期三 15时00分56秒
     ***************************************************************/
    
    #include <map>
    #include <set>
    #include <list>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pii        pair<int, int>
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 5e3 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e6 + 3;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m, A, B;
    int cas, tol, T;
    
    map<int, int> mp;
    
    void handle() {
    	mp.clear();
    	for(int i='a'; i<='z'; i++) {
    		mp[i] = i-'a'+1;
    	}
    	for(int i='A'; i<='Z'; i++) {
    		mp[i] = i-'A'+1;
    	}
    	int cnt = 26;
    	for(int i='0'; i<='9'; i++) {
    		if(i=='0')	mp[i] = mp['o'];
    		else if(i == '1')	mp[i] = mp['i'];
    		else if(i == '3')	mp[i] = mp['e'];
    		else if(i == '5')	mp[i] = mp['s'];
    		else if(i == '7')	mp[i] = mp['t'];
    		else mp[i] = ++cnt;
    	}
    }
    struct AC {
    	int node[maxn][35], fail[maxn], cnt[maxn];
    	ll dp[10][25][maxn];
    	int root, sz;
    	int newnode() {
    		mes(node[++sz], 0);
    		cnt[sz] = 0;
    		return sz;
    	}
    	void init() {
    		sz = 0;
    		root = newnode();
    	}
    	void insert(char *s) {
    		int len = strlen(s+1);
    		int rt = root;
    		for(int i=1; i<=len; i++) {
    			int k = mp[s[i]];
    			if(node[rt][k] == 0)	node[rt][k] = newnode();
    			rt = node[rt][k];
    		}
    		cnt[rt] = 1;
    	}
    	void build() {
    		queue<int> q;
    		while(!q.empty())	q.pop();
    		fail[root] = root;
    		for(int i=1; i<=31; i++) {
    			if(node[root][i] == 0) {
    				node[root][i] = root;
    			} else {
    				fail[node[root][i]] = root;
    				q.push(node[root][i]);
    			}
    		}
    		while(!q.empty()) {
    			int u = q.front();
    			cnt[u] |= cnt[fail[u]];
    			q.pop();
    			for(int i=1; i<=31; i++) {
    				if(node[u][i] == 0) {
    					node[u][i] = node[fail[u]][i];
    				} else {
    					fail[node[u][i]] = node[fail[u]][i];
    					q.push(node[u][i]);
    				}
    			}
    		}
    	}
    	ll solve(int A, int B) {
    		for(int i=0; i<=7; i++) {
    			for(int j=0; j<=B; j++) {
    				for(int k=0; k<=sz; k++) {
    					dp[i][j][k] = 0;
    				}
    			}
    		}
    		dp[0][0][1] = 1;
    		for(int i=0; i<B; i++) {
    			for(int j=1; j<=sz; j++) {
    				if(cnt[j])	continue;
    				for(int st=0; st<=7; st++) {
    					if(dp[st][i][j] == 0)	continue;
    					// printf("dp[%d][%d][%d] = %lld
    ", st, i, j, dp[st][i][j]);
    					for(int k='a'; k<='z'; k++) {
    						int nst = node[j][mp[k]];
    						if(cnt[nst])	continue;
    						dp[st|1][i+1][nst] += dp[st][i][j];
    						dp[st|2][i+1][nst] += dp[st][i][j];
    						dp[st|1][i+1][nst] %= mod;
    						dp[st|2][i+1][nst] %= mod;
    					}
    					for(int k='0'; k<='9'; k++) {
    						int nst = node[j][mp[k]];
    						if(cnt[nst])	continue;
    						dp[st|4][i+1][nst] += dp[st][i][j];
    						dp[st|4][i+1][nst] %= mod;
    					}
    				}
    			}
    		}
    		ll ans = 0;
    		for(int i=A; i<=B; i++) {
    			for(int j=1; j<=sz; j++) {
    				if(dp[7][i][j] == 0)	continue;
    				// printf("dp[7][%d][%d] = %lld
    ", i, j, dp[7][i][j]);
    				ans = (ans + dp[7][i][j])%mod;
    			}
    		}
    		return ans;
    	}
    } ac;
    char s[maxn];
    
    int main() {
    	handle();
    	ac.init();
    	scanf("%d%d", &A, &B);
    	scanf("%d", &n);
    	for(int i=1; i<=n; i++) {
    		scanf("%s", s+1);
    		ac.insert(s);
    	}
    	ac.build();
    	ll ans = ac.solve(A, B);
    	printf("%lld
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Nhibernate对应关系参数介绍
    jquery mobile 登陆后页面验证
    jquery mobile radio,checkbox button 样式设置
    jquery mobile button样式设置
    Ext 三级联动 及附值
    store操作
    Javascript中try finally的细微差别
    mysql entity framework生成画面崩溃
    PYTHON推导生成
    PYTHON修饰器
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/10833712.html
Copyright © 2011-2022 走看看