Question: How many substrings do not contain A,, B <= 10 ^ 200, total virus String Length <= 2000.
Solution: because of the time problem, this is the last question I have discussed about AC automation. Ac A is very nice, but other aspects are too weak, so I have to review other aspects.
After reading the question, I kneel down to the problem creator. The two things that seem unrelated but actually have a connection are combined. The obvious status on the AC automatic machine makes it easy for us to perform DP on the AC automatic machine, while the digital DP is a typical DP in the DP, previously, I always thought that the digital DP should be constructed by a digit directly and one digit. This question uses an automatic mechanism to create a matrix between the number and other numbers, then, use this matrix for digital DP. This analysis does not seem unrelated.
Starting from the end, let's first analyze why the last digit dp needs to use an automatic machine. If a number does not contain a virus string, all the numbers in this number are compiled into BCD codes and must not contain a virus string after being connected. There are no restrictions on the two adjacent numbers constructed by a common digital DP, and there are two constraints on this question. First, the numbers may contain virus strings after being compiled into BCD codes, second, after two numbers are connected, their BCD code may also be connected, which may contain virus strings. The first is a special case of the second. In this way, the problem becomes that we construct several strings so that these strings do not contain virus strings. When the problem changes, it is related to the AC automatic machine. We can use this string to go to the ac automatic machine and run it to know that the string contains no virus.
We need to compress the status on the automatic machine into a mat [MAXSIZE] [10] matrix, mat [I] [j] indicates the position I reaches after passing through the BCD code compiled by j, that is, the four-digit binary number. If it cannot be reached, it is set to-1. then we use mat to perform digital DP. I in mat [I] [j] represents the position, but it also represents the number except root, I-> next [k] = ii, here, ii represents k.
Dp [pos] [ac] [limit] [zero] is used to represent the status. pos indicates the number of digits, and ac indicates the location on the ac automatic machine, limit = 0 indicates that there is no upper limit. limit = 1 indicates that the upper limit is digit [pos], and zero indicates that the upper limit is non-leading 0, in this case, you need to determine whether mat [ac] [k] is-1. If it is-1, the next digit k cannot be constructed. Otherwise, it can be constructed. If zero is 1, it indicates that it is the leading 0, if the next value is 0, it indicates that these values are useless. If the next value is 0, it should be root. If the value is not 0, You Need To determine mat [0] [k.
After the status is clear, it will be easy to write with the memory-based search.
Test data:
Input:
10
0
1 10
1
00
1 10
1
00
1 100
1
1111
1 100
2
01
10
1 100
Output:
10
3
9
98
0
Code:
[Cpp]
# Include <stdio. h>
# Include <string. h>
# Include <queue>
# Include <algorithm>
Using namespace std;
# Define MAXNODE 2
# Define Max size 2100
# Define MOD 1000000009.
Int n, m;
Int ans;
Char str [MAXSIZE];
Char A [MAXSIZE], B [MAXSIZE];
Struct ACnode {
Int flag, in;
ACnode * next [MAXNODE], * fail, * father;
};
Struct AC_Auto {
Int head, tail, total;
Int digit [210];
Int ans, dp [210] [MAXSIZE] [2] [2];
Int next [MAXSIZE] [10];
ACnode * root, * p, * q;
ACnode * qu [MAXSIZE], tree [MAXSIZE];
Void Initial (){
Total = 0;
Head = tail = 0;
Root = CreateNode ();
Root-> fail = root;
}
ACnode * CreateNode (){
Tree [total]. flag = 0;
Tree [total]. in = total;
Tree [total]. next [0] = NULL;
Tree [total]. next [1] = NULL;
Return & tree [total ++];
}
Int GetHash (char c ){
Return c-'0 ';
}
Void Insert (char * str ){
P = root;
For (int I = 0; str [I]; ++ I ){
Int k = GetHash (str [I]);
If (p-> next [k] = NULL)
P-> next [k] = CreateNode ();
P = p-> next [k];
}
P-> flag = 1;
}
Void Build_AC (){
Qu [head ++] = root;
While (tail
P = qu [tail ++];
For (int k = 0; k <MAXNODE; ++ k)
If (p-> next [k]) {
If (p = root) p-> next [k]-> fail = root;
Else p-> next [k]-> fail = p-> fail-> next [k];
P-> next [k]-> flag | = p-> next [k]-> fail-> flag;
Qu [head ++] = p-> next [k];
}
Else {
If (p = root) p-> next [k] = root;
Else p-> next [k] = p-> fail-> next [k];
}
}
}
Int Next (int pos, int num ){
If (tree [pos]. flag = 1) return-1;
Int realpos = pos;
For (int I = 3; I> = 0; -- I ){
Int k = (num> I) & 1 );
If (tree [realpos]. next [k]-> flag! = 1)
Realpos = tree [realpos]. next [k]-> in;
Else return-1;
}
Return realpos;
}
Void Cal_Next (){
For (int I = 0; I <total; ++ I)
For (int j = 0; j <= 9; ++ j)
Next [I] [j] = Next (I, j );
}
Int Dfs (int pos, int ac, int limit, int zero ){
If (pos =-1) return 1;
If (dp [pos] [ac] [limit] [zero]! =-1)
Return dp [pos] [ac] [limit] [zero];
Int sum = 0;
Int tl, tz, end = limit? Digit [pos]: 9;
For (int I = 0; I <= end; ++ I ){
Tz = zero & I = 0;
Tl = limit & (I = end );
If (tz = 1 ){
Sum = sum + Dfs (pos-1, 0, tl, tz );
If (sum> = MOD) sum-= MOD;
Continue;
}
If (next [ac] [I] =-1) continue;
Sum = sum + Dfs (pos-1, next [ac] [I], tl, tz );
If (sum> = MOD) sum-= MOD;
}
Dp [pos] [ac] [limit] [zero] = sum;
Return dp [pos] [ac] [limit] [zero];
}
Int Cal (char * num ){
Int pos;
Memset (dp,-1, sizeof (dp ));
Reverse (num, num + strlen (num ));
For (pos = 0; num [pos]; ++ pos)
Digit [pos] = num [pos]-'0 ';
Return Dfs (pos-1, 1 );
}
Void Debug (){
For (int I = 0; I <total; ++ I)
For (int j = 0; j <= 9; ++ j)
Printf ("I = % d j = % d next = % d \ n", I, j, next [I] [j]);
}
} AC;
Void Subtoone (char * ){
Int len = strlen (A), I = len-1;
If (A [I] = 0 ){
A [I] = '9 ';
While (A [I] = '0') I --;
}
A [I] = A [I]-'0'-1 + '0 ';
}
Int main ()
{
Int I, j, k, t;
Scanf ("% d", & t );
While (t --){
Scanf ("% d", & n );
AC. Initial ();
For (I = 1; I <= n; ++ I ){
Scanf ("% s", str );
AC. Insert (str );
}
Ans = 0;
AC. Build_AC ();
AC. Cal_Next ();
// AC. Debug ();
Scanf ("% s", );
Subtoone ();
Ans = ans-AC. Cal ();
If (ans <0) ans + = MOD;
Scanf ("% s", B );
Ans = ans + AC. Cal (B );
If (ans> = MOD) ans-= MOD;
Printf ("% d \ n", ans );
}
}