题目链接:点这里
题意:
让你构造一个长度范围在[A,B]之间 字符串(大小写字母,数字),问你有多少种方案
需要满足条件一下:
1:构成串中至少包含一个数字,一个大写字母,一个小写字母;
2:不能包含给定的N个病毒串
3:遵循一堆映射规则
题解:
将病毒串建立AC自动机
设定dp[i][j] [0/1][0/1][0/1]:表示构造长度为i,在自动机上面的状态是j,分别是否含有数字,大写字母,小写字母的情况
你能转移的点就是 加上一个数字或者大小写字母,暴力转移DP就好了,方程复杂度:20*1000*8,转移复杂度:26+26+10
整体复杂度:20*1000*8*62+建立trie
#include<bits/stdc++.h> using namespace std; #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; const long long INF = 1e18+1LL; const double Pi = acos(-1.0); const int N = 1e6+10, M = 1e3+20; LL mod = 1000003; int nex[5500][70],q[55000],fail[5500],cnt=1,black[55000],head,tail; int rea_ID(int ch) { if(ch >= 0 && ch < 26) return ch; if(ch == 26) return 'o'-'a'; if(ch == 27) return 'i'-'a'; if(ch == 29) return 'e'-'a'; if(ch == 31) return 's'-'a'; if(ch == 33) return 't'-'a'; if(ch >= 26 && ch <= 35) return 26; if(ch > 35 && ch <= 61)return ch - 36; } int ID(char ch) { return ch - 'a'; } void insert(char *s) { int now = 1, len = strlen(s); for(int i = 0; i < len; ++i) { int index = ID(s[i]); if(!nex[now][index]) nex[now][index] = ++cnt; now = nex[now][index]; } black[now] |= 1; } void build_fail() { head = 0, tail = 0; for(int i = 0; i < 26; ++i) nex[0][i] = 1; fail[1] = 0; q[tail++] = 1; while(head != tail) { int now = q[head++]; black[now] |= black[fail[now]]; for(int i = 0; i < 26; ++i) { int p = fail[now]; if(!nex[now][i]) { nex[now][i] = nex[p][i];continue; } fail[nex[now][i]] = nex[p][i]; q[tail++] = nex[now][i]; } nex[now][26] = 1; } } int A,B,n; char s[500]; LL dp[30][5500][2][2][2]; int main() { scanf("%d%d",&A,&B); scanf("%d",&n); for(int i = 1; i <= n; ++i) { scanf("%s",s); insert(s); } build_fail(); dp[0][1][0][0][0] = 1; for(int i = 0; i <= B; ++i) { for(int j = 1; j <= cnt; ++j) { for(int dxziok = 0; dxziok <= 1; ++dxziok) for(int shuziok = 0; shuziok <= 1; ++shuziok) for(int xxziok = 0; xxziok <= 1; ++xxziok) { if(dp[i][j][dxziok][shuziok][xxziok] == 0) continue; for(int k = 0; k <= 61; ++k) { int rea = rea_ID(k); int tmp1 = 0,tmp2 = 0,tmp3 = 0; if(k < 26) tmp1 = 1; else if(k <= 35) tmp2 = 1; else tmp3 = 1; if(!black[nex[j][rea]]) dp[i+1][nex[j][rea]][dxziok|tmp1][shuziok|tmp2][xxziok|tmp3] += dp[i][j][dxziok][shuziok][xxziok]; dp[i+1][nex[j][rea]][dxziok|tmp1][shuziok|tmp2][xxziok|tmp3]%=mod; } } } } LL ans = 0; for(int i = A; i <= B; ++i) { for(int j = 1; j <= cnt; ++j) { ans = (ans + dp[i][j][1][1][1])%mod; } } cout<<ans<<endl; return 0; }