Bzoj4259: 残缺的字符串

题面

没有权限号的我当然选择luogu

Sol

假设没有通配符
那么把 T T 翻转
f[i]=j+k=i[S[k]==T[j]]
如果 f[i] f [ i ] 0 0 i之前的一一匹配
那么可以给每个字符一个权值
重新定义 f[i]=j+k=i(S[k]T[j])2 f [ i ] = ∑ j + k = i ( S [ k ] − T [ j ] ) 2
就可以 FFT F F T

然后有通配符,设权值为 0 0
再定义
f[i]=j+k=i(S[k]T[j])2S[k]T[j]

然后拆开 FFT F F T 就可以了

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;

template <class Int>
IL void Input(RG Int &x){
    RG int z = 1; RG char c = getchar(); x = 0;
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    x *= z;
}

const int maxn(3e5 + 5);
const int oo(1e9);
const double pi(acos(-1));

int n, m, k, r[maxn << 2], len, cnt, v1[maxn], v2[maxn], ans[maxn];
char s[maxn], t[maxn];

struct Complex{
    double real, image;

    IL Complex(){
        real = image = 0;
    }

    IL Complex(RG double a, RG double b){
        real = a, image = b;
    }

    IL Complex operator +(RG Complex b){
        return Complex(real + b.real, image + b.image);
    }

    IL Complex operator -(RG Complex b){
        return Complex(real - b.real, image - b.image);
    }

    IL Complex operator *(RG Complex b){
        return Complex(real * b.real - image * b.image, real * b.image + image * b.real);
    }

    IL Complex operator *(RG int b){
        return Complex(real * b, image * b);
    }
} a[maxn << 2], b[maxn << 2], w[maxn << 2], c[maxn << 2];

IL void FFT(RG Complex *p, RG int opt){
    for(RG int i = 0; i < len; ++i) if(r[i] < i) swap(p[i], p[r[i]]);
    for(RG int i = 1; i < len; i <<= 1)
        for(RG int j = 0, l = i << 1; j < len; j += l){
            for(RG int k = 0; k < i; ++k){
                RG Complex wn = Complex(w[len / i * k].real, w[len / i * k].image * opt);
                RG Complex x = p[k + j], y = wn * p[k + j + i];
                p[k + j] = x + y, p[k + j + i] = x - y;
            }
        }
}

IL void Prepare(){
    RG int l = 0, tmp = m + n - 1;
    for(len = 1; len < tmp; len <<= 1) ++l;
    for(RG int i = 0; i < len; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    for(RG int i = 1; i <= len; i <<= 1)
        for(RG int k = 0; k < i; ++k)
            w[len / i * k] = Complex(cos(pi / i * k), sin(pi / i * k));
}

int main(RG int argc, RG char* argv[]){
    Input(m), Input(n), scanf(" %s %s", t, s);
    reverse(t, t + m), Prepare();
    for(RG int i = 0; i < n; ++i) v1[i] = s[i] == '*' ? 0 : s[i] - 'a' + 1;
    for(RG int i = 0; i < m; ++i) v2[i] = t[i] == '*' ? 0 : t[i] - 'a' + 1;

    for(RG int i = 0; i < n; ++i) a[i].real = v1[i] * v1[i] * v1[i];
    for(RG int i = 0; i < m; ++i) b[i].real = v2[i];
    FFT(a, 1), FFT(b, 1);
    for(RG int i = 0; i < len; ++i) c[i] = c[i] + a[i] * b[i], a[i] = b[i] = Complex(0, 0);

    for(RG int i = 0; i < n; ++i) a[i].real = v1[i] * v1[i] << 1;
    for(RG int i = 0; i < m; ++i) b[i].real = v2[i] * v2[i];
    FFT(a, 1), FFT(b, 1);
    for(RG int i = 0; i < len; ++i) c[i] = c[i] - a[i] * b[i], a[i] = b[i] = Complex(0, 0);

    for(RG int i = 0; i < n; ++i) a[i].real = v1[i];
    for(RG int i = 0; i < m; ++i) b[i].real = v2[i] * v2[i] * v2[i];
    FFT(a, 1), FFT(b, 1);
    for(RG int i = 0; i < len; ++i) c[i] = c[i] + a[i] * b[i];

    FFT(c, -1);
    for(RG int i = m - 1; i < n; ++i)
        if(!(int(c[i].real / len + 0.5))) ans[++cnt] = i;
    printf("%d\n", cnt);
    for(RG int i = 1; i <= cnt; ++i) printf("%d ", ans[i] - m + 2);
    return puts(""), 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值