[Test1.11-T1]匹配 Matching

Description:

给定两个含小写字母、通配符的字符串 \(S\), \(T\)
出于简化问题的考虑,这里的通配符只有"\(?\)"一种。它可以匹配任意一个字符。
一个串 \(T\)\(S\)\({pos}\) 位置上出现,当且仅当:
∀1 ≤ i ≤ |T|, Spos+i 1 = Ti | Spos+i 1 =′?′ | Ti =′?′
你的任务是:求 T 在 S 中的出现次数。

数据范围:

|T| ≤ |S| ≤ 2 × 1e5
时限:3s
空间:128mb

Solution:

solution

代码:

#include<iostream>
#include<cstdio>
#include<complex>
#include<cstring>
#define R register
#define ll long long
#define eps 1e-8
#define is0(x) ((x) < eps && -(x) < eps)
using namespace std;
namespace IO
{
    template<class T>
    void rea(T &x)
    {
        char ch=getchar();long long f(0);x = 0;
        while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        x = f?-x:x;
    }
    template<class T>
    T max(T a, T b){return (a>b?a:b);}
    template<class T>
    T min(T a, T b){return (a<b?a:b);}
}
const long long N = 600005;
char s[N], t[N], pre[N];
long long pos[N], tot, lens, lent, ans[N];
complex<double>a[N], b[N], x[N], y[N];
void init(long long k)
{
    long long len = 1<<k;
    for(R long long i = 0; i < len; ++i)
        pos[i] = (pos[i>>1]>>1)|((i&1)<<(k-1));
}
void fft(complex<double> *a, long long n, long long flag)
{
    for(R long long i = 0; i < n; ++i) if(i < pos[i]) swap(a[i], a[pos[i]]);
    for(R long long len = 1; len < n; len *= 2)
    {
        complex<double> wx = complex<double>(cos(M_PI/len), flag*sin(M_PI/len));
        for(R long long i = 0; i < n; i += len*2)
        {
            complex<double> w(1, 0);
            for(R long long j = i; j < i+len; ++j)
            {
                complex<double> x = a[j];
                complex<double> y = w*a[j+len];
                a[j] = x+y;
                a[j+len] = x-y;
                w *= wx;
            }
        }
    }
    if(flag == -1) for(R long long i = 0; i < n; ++i) a[i] /= n;
}
void solve(long long flag, long long n)
{
    fft(x, n, 1);fft(y, n, 1);
    for(R long long i = 0; i < n; ++i) x[i] *= y[i];
    fft(x, n, -1);
    for(R long long i = 0; i < n; ++i) ans[i] += (long long)(x[i].real()+0.5)*flag;
}
int main()
{
    freopen("matching.in","r",stdin);
    freopen("matching.out","w",stdout);
    scanf("%s%s", s, pre);
    lens = strlen(s), lent = strlen(pre);
    for(R long long i = 0; i < lent; ++i) t[i] = pre[lent-i-1];
    for(R long long i = 0; i < lens; ++i) a[i] = (double)((s[i]=='?'?0 : s[i]-'a'+1));
    for(R long long i = 0; i < lent; ++i) b[i] = (double)((t[i]=='?'?0 : t[i]-'a'+1));
    long long P = 1, k = 0;
    while(P <= lens+lent) P <<= 1, k++;
    init(k);
    for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i]*a[i], y[i] = b[i];
    solve(1, P);
    for(R long long i = 0; i < P; ++i) x[i] = a[i], y[i] = b[i]*b[i]*b[i];
    solve(1, P);
    for(R long long i = 0; i < P; ++i) x[i] = a[i]*a[i], y[i] = b[i]*b[i];
    solve(-2, P);
    for(R long long i = lent-1; i < lens; ++i) if(is0(ans[i])) tot++;
    printf("%d\n", tot);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heanda/p/12398591.html
今日推荐