General idea of the topic
Here are two strings, one of length n n n-mode string with a length of m m m matching string, composed of characters 0 0 0 to 9 9 9 and wildcard *. Ask you if the mismatch length of the matching string in the pattern string does not exceed 0 , 1 , ⋯ , m 0, 1,\cdots,m How many strings are there for 0,1,..., m.
Problem solving ideas
Consider adopting
f
f
t
fft
fft to do.
Pretreatment
For pattern strings, we open ten arrays (buckets) to mark
0
0
0 to
9
9
The subscript of 9 appears. If it appears, it is marked as
1
1
1, otherwise marked as
0
0
0, for wildcards
∗
*
* will
0
0
0 to
9
9
9 are marked as
1
1
1. Because wildcards can match any character, they can contribute.
For the matching string, first reverse the matching string, and then do the same processing as the pattern string. The only difference is the processing of wildcards. Wildcards in a pattern string cannot mark all positions as
1
1
1. In this case, if both the pattern string and the matching string are wildcards, the calculation will be repeated, so we first count the number of wildcards in the matching string and mark all positions of wildcards as
0
0
0, add the number of wildcards when calculating the answer at last.
For example
012
∗
4
012*4
012∗4
1
∗
3
1*3
1∗3
The result of pattern string preprocessing is
10010 01010 00110 00010 00011 00000 00000 00000 00000 00000
use
f
f
t
fft
Fast fft processing
Defines the second in the pattern string
i
i
The i string is, and the second string is
i
i
i characters, length
m
m
Continuous substring of m. (
i
i
i from
0
0
0 (start)
Using the in the pattern string
0
0
0 array and in matching string
0
0
0 array do
f
f
t
fft
fft can get
f
f
t
fft
Array after fft
a
a
a. among
a
m
−
i
−
1
a_{m-i-1}
am − i − 1 is the second of the mode string
i
i
i strings and matching strings
0
0
Number of matches for 0.
We are right
0
0
0 to
9
9
9 once per array
f
f
t
fft
fft, and then sum each time
a
m
−
i
−
1
a_{m-i-1}
am − i − 1, plus the number of wildcards in the matching string, you can get the second string
i
i
i maximum matching length of pattern string and matching string.
Find the answer
Finally, we count a mismatch as
0
0
0 to mismatch is
m
m
m prefix and.
Inversion is important
Like you want to know
a
1
,
a
2
,
a
3
a_1, a_2, a_3
a1, a2, a3 +
b
1
,
b
2
,
b
3
b_1,b_2,b_3
How many of b1, b2, b3} are matched? If you don't reverse the second string, your result will exist
c
2
,
c
4
,
c
6
c_2, c_4, c_6
c2, c4, c6 , because
c
2
=
a
1
×
b
1
,
c
4
=
a
2
×
b
2
,
c
6
=
a
3
×
b
3
c_2 = a_1\times b_1, c_4=a_2\times b_2, c_6 = a_3\times b_3
c2=a1 × b1,c4=a2 × b2,c6=a3 × b3, but the result exists directly after inversion
c
4
c_4
c4 , because
c
4
=
a
1
×
b
3
+
a
2
×
b
2
+
a
3
×
b
1
c_4 = a_1\times b_3 + a_2\times b_2 + a_3\times b_1
c4=a1 × b3+a2 × b2+a3 × b1, that's us
f
f
t
fft
The meaning of fft.
Code
#include <bits/stdc++.h> #define ll long long #define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0) #define fi first #define se second #define PII pair<int, int> #define PLL pair<ll, ll> #define pb push_back using namespace std; const int MAXN = 1e6 + 7; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll mod = 1e9 + 7; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } char s[MAXN],t[MAXN]; int f[10][MAXN]; int g[10][MAXN]; int n, m; const double PI = acos(-1.0); struct Complex { double x, y; Complex operator+(const Complex &W) const { return {x + W.x, y + W.y}; } Complex operator-(const Complex &W) const { return {x - W.x, y - W.y}; } Complex operator*(const Complex &W) const { return {x * W.x - y * W.y, x * W.y + y * W.x}; } }; Complex a[MAXN], b[MAXN]; int R[MAXN]; int tot, bit; void inif(int n) { tot = 1, bit = 0; while (tot <= n) tot <<= 1, ++bit; for (int i = 0; i <= tot; ++i) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (bit - 1)); } void FFT(Complex f[], int total, int type, int n, int m) { for (int i = 0; i < total; ++i) if (i < R[i]) swap(f[i], f[R[i]]); for (int tot = 2; tot <= total; tot <<= 1) { Complex w1 = {cos(2 * PI / tot), type * sin(2 * PI / tot)}; for (int pos = 0; pos < total; pos += tot) { Complex w = {1, 0}; for (int i = pos; i < pos + tot / 2; ++i, w = w * w1) { Complex x = f[i]; Complex y = w * f[i + tot / 2]; f[i] = x + y; f[i + tot / 2] = x - y; } } } if (type == -1) { for (int i = 0; i <= n + m; ++i) f[i].x = (int)(f[i].x / tot + 0.5); } } // usage int tong[MAXN]; int ans[MAXN]; int pre[MAXN]; void solve(){ cin >> n >> m; cin >> (s) >> (t); for (int i = 0; i < n; ++i){ if(s[i] == '*'){ for (int j = 0; j <= 9; ++j){ f[j][i] = 1; } } else f[s[i]-'0'][i] = 1; } int cnt = 0; reverse(t, t+m); for (int i = 0; i < m; ++i){ if(t[i] == '*') cnt++; else g[t[i]-'0'][i] = 1; } for(int i = 0; i <= 9; ++i){ for (int j = 0; j < n; ++j){ a[j].x = f[i][j]; } for (int j = 0; j < m; ++j){ b[j].x = g[i][j]; } inif(n + m); FFT(a, tot, 1, n, m), FFT(b, tot, 1, n, m); for (int j = 0; j <= tot-1; ++j){ a[j] = a[j] * b[j]; } FFT(a, tot, -1, n, m); // Start processing for (int j = m-1; j <= n-1; ++j){ tong[j] += (int)a[j].x; } for (int j = 0; j <= tot; ++j){ a[j].x = a[j].y = b[j].x = b[j].y = 0; } } for (int i = m-1; i <= n-1; ++i){ ans[tong[i] + cnt]++; } pre[m+1] = 0; for(int i = m; i >= 0; --i){ pre[i] = pre[i+1] + ans[i]; } for(int i = m; i >= 0; i--) cout << pre[i] << "\n"; for(int i = m-1; i <= n-1; i++) tong[i] = 0; for (int i = 0; i <= m; ++i){ ans[i] = 0; } for (int i = 0; i <= 9; ++i){ for (int j = 0; j <= n; ++j){ f[i][j] = g[i][j] = 0; } } } signed main() { #ifdef ONLINE_JUDGE #else freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif qc; int T; cin >> T; //T = 1; while(T--){ solve(); } return 0; }