BZOJ4259 殘缺的字串 (FFT)

2021-07-10 02:12:11 字數 1516 閱讀 9702

題意:定義*號可匹配任意字元。給出a串,b串,求a串在b中完全匹配的所有位置。

將*號視作0,則兩個等長的串可匹配當且僅當σ(a[i]-b[i])^2*a[i]*b[i]==0。將a串和b串最左邊對齊,每次上式都要重算一次,不科學。所以講a串先反轉過來然後補上*號,就是卷積啦。

原來的萬徑人蹤滅一題當中用fft來求了回文串,這裡又能玩字串匹配,真是太6了。

#include#include#include#include#includeusing namespace std;

#define rep(i,a,b) for(int i=a;i<=b;++i)

#define clr(a) memset(a,0,sizeof a)

#define db double

const int maxn = 300005;

const int maxl = maxn*4;

int n, m;

const db pi = acos(-1);

struct cpx

cpx(db a, db b):r(a), i(b){};

inline cpx operator + (cpx b)

inline cpx operator - (cpx b)

inline cpx operator * (cpx b)

};namespace fft

}char a[maxn], b[maxn];

db p1[maxn*2], p2[maxn*2], f[maxn];

int an, ans[maxn];

int main()

rep(i, 0, m-1)

rep(i, 0, n-1) p1[i] = 1.0*a[i]*a[i]*a[i];

rep(i, 0, m-1) p2[i] = b[i];

fft::mul(p1, p2, n-1, m-1);

rep(i, 0, m-1) f[i] += p1[i];

rep(i, 0, n-1) p1[i] = 1.0*a[i]*a[i];

rep(i, 0, m-1) p2[i] = 1.0*b[i]*b[i];

fft::mul(p1, p2, n-1, m-1);

rep(i, 0, m-1) f[i] -= 2*p1[i];

rep(i, 0, n-1) p1[i] = a[i];

rep(i, 0, m-1) p2[i] = 1.0*b[i]*b[i]*b[i];

fft::mul(p1, p2, n-1, m-1);

rep(i, 0, m-1) f[i] += p1[i];

rep(i, n-1, m-1) if (int(f[i]+0.2)==0) ans[++an] = i+1-(n-1);

printf("%d\n", an);

rep(i, 1, an) printf("%d%c", ans[i], i!=an?' ':'\n');

return 0;

}

BZOJ4259 殘缺的字串

給出兩個字串,乙個模式串,乙個匹配串,問匹配串中哪些位置可以匹配上模式串,其中 可以作任意字元。這個可以轉化為多項式,我們可以把 看作0,其他字母看作各個數字,然後發現如果兩個字串相同,當且僅當 i 0n 1 a i b i 2 a i b i 0 sum 0 i 0n 1 a i b i 2 a ...

BZOJ4259 殘缺的字串

其實大部分字串的題都可以用多項式來想,包括這道題。於是,我們可以嘗試去構造兩個多項式,使其乘後的係數為0即可。相等為0,那麼我們可以用減法表示。可 可以匹配所有的符號,我們又該咋辦?那不就相當於乘個0嘛。於是,我們得到了下式 然後就可以卷積計算了。include include include in...

bzoj 4259 殘缺的字串

這題好神啊,居然是fft,表示一直在往資料結構上想。把 當成0,那麼兩個串可以匹配當且僅當 sum a i b i 2 times a i times b i 0 我們可以把平方拆開,然後就變成了幾個乘積相加的形式,那就大力翻轉乙個串然後跑fft。因為最開始mle了所以複製貼上了好多東西。1 inc...