2021 Hangdian multi School Game 3 1003 - giving matching

Posted by future_man on Thu, 16 Dec 2021 23:22:04 +0100

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;
}

Topics: NTT