您的位置:首页 > 其它

省队集训 Day1 残缺的字符串

2017-07-09 21:05 281 查看
【题目大意】

双串带通配符匹配。

$|S|, |T| \leq 5 * 10^5$

TL: 2s

【题解】

参考bzoj 4503

可以设计如下函数 A[i] * B[i] * (A[i] - B[i])^2

如果有通配符,A[i] = 0,否则,A[i] = s[i] - 'a' + 1;B同理。

可以自行验证,这是一种很妙的设计。

然后就是卷积的事情了。大概做9次DFT。

可以用类似于MTT的技巧搞到4次,不会写。

# include <math.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10, N = 2e6 + 10;
const int mod = 1e9+7;
const ld pi = acos(-1.0);

char s[M], t[M];
int A[M], B[M], ns, nt;

struct cp {
ld x, y;
cp() {}
cp(ld x, ld y) : x(x), y(y) {}
friend cp operator + (cp a, cp b) {
return cp(a.x + b.x, a.y + b.y);
}
friend cp operator - (cp a, cp b) {
return cp(a.x - b.x, a.y - b.y);
}
friend cp operator * (cp a, cp b) {
return cp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}
}a
, b
, ans
;

namespace FFT {
int n, lst
; cp w[2]
;
inline void set(int _n) {
n = 1;
while(n < _n) n <<= 1;
for (int i=0; i<n; ++i) w[0][i] = cp(cos(pi * 2 / n * i), sin(pi * 2 / n * i)), w[1][i] = cp(w[0][i].x, -w[0][i].y);
int len = 0;
while((1<<len) < n) ++len;
for (int i=0; i<n; ++i) {
int t = 0;
for (int j=0; j<len; ++j) if(i & (1<<j)) t |= (1<<(len-j-1));
lst[i] = t;
}
}
inline void DFT(cp *a, int op) {
cp *o = w[op];
for (int i=0; i<n; ++i) if(i < lst[i]) swap(a[i], a[lst[i]]);
for (int len=2; len<=n; len<<=1) {
int m = len>>1;
for (cp *p=a; p!=a+n; p+=len) {
for (int k=0; k<m; ++k) {
cp t = o[n/len*k] * p[k+m];
p[k+m] = p[k] - t;
p[k] = p[k] + t;
}
}
}
if(op) {
for (int i=0; i<n; ++i) a[i].x /= (ld)n, a[i].y /= (ld)n;
}
}
}

# define L FFT::n

int main() {
scanf("%s%s", t, s); ns = strlen(s), nt = strlen(t);
for (int i=0; i<ns; ++i) A[i] = (s[i] == '*' ? 0 : s[i] - 'a' + 1);
for (int i=0; i<nt; ++i) B[i] = (t[i] == '*' ? 0 : t[i] - 'a' + 1);
reverse(B, B+nt);
// (A[i] - B[i])^2 * A[i] * B[i]  =  A[i]^3 * B[i] + A[i] * B[i]^3 - A[i]^2 * B[i]^2
FFT :: set(max(ns, nt));
for (int i=0; i<ns; ++i) a[i] = cp(A[i] * A[i] * A[i], 0);
for (int i=ns; i<L; ++i) a[i] = cp(0, 0);
for (int i=0; i<nt; ++i) b[i] = cp(B[i], 0);
for (int i=nt; i<L; ++i) b[i] = cp(0, 0);
FFT :: DFT(a, 0); FFT :: DFT(b, 0);
for (int i=0; i<L; ++i) ans[i] = ans[i] + a[i] * b[i];
for (int i=0; i<ns; ++i) a[i] = cp(A[i], 0);
for (int i=ns; i<L; ++i) a[i] = cp(0, 0);
for (int i=0; i<nt; ++i) b[i] = cp(B[i] * B[i] * B[i], 0);
for (int i=nt; i<L; ++i) b[i] = cp(0, 0);
FFT :: DFT(a, 0); FFT :: DFT(b, 0);
for (int i=0; i<L; ++i) ans[i] = ans[i] + a[i] * b[i];
for (int i=0; i<ns; ++i) a[i] = cp(A[i] * A[i] * 2, 0);
for (int i=ns; i<L; ++i) a[i] = cp(0, 0);
for (int i=0; i<nt; ++i) b[i] = cp(B[i] * B[i], 0);
for (int i=nt; i<L; ++i) b[i] = cp(0, 0);
FFT :: DFT(a, 0); FFT :: DFT(b, 0);
for (int i=0; i<L; ++i) ans[i] = ans[i] - a[i] * b[i];
FFT :: DFT(ans, 1);
for (int i=nt-1; i<ns; ++i) {
if((int)(ans[i].x-0.5) == 0) printf("%d ", i-nt+2);
}
puts("");
return 0;
}


View Code
可能是noi前最后一次复习FFT了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: