bzoj 4259 殘缺的字串

2022-06-03 08:48:12 字數 1523 閱讀 4527

目錄很久很久以前,在你剛剛學習字串匹配的時候,有兩個僅包含小寫字母的字串a和b,其中a串長度為m,b串長度為n。可當你現在再次碰到這兩個串時,這兩個串已經老化了,每個串都有不同程度的殘缺。

你想對這兩個串重新進行匹配,其中a為模板串,那麼現在問題來了,請回答,對於b的每乙個位置i,從這個位置開始連續m個字元形成的子串是否可能與a串完全匹配?

原題鏈結。

據說已經成了套路題。

以下內容中假定以 0 為字串下標起點。

考慮沒有萬用字元的情況,b 中第 j 個位置開頭的串能否與 a 匹配。實際上是計算式子 \(\sum_^[a_i\not = b_]\) 是否為 0。

注意到這個注意匹配的形式很像卷積。不過別急,我們先把其拆成數值計算的形式:上式為 0 等價於 \(\sum_^(a_i - b_)^2\)。

由完全平方的非負性可以得到等價性。

有萬用字元怎麼辦?a, b 其中乙個為萬用字元,構造出來的式子就應該等於 0。

不妨令萬用字元等於 0,則計算 \(\sum_^(a_i - b_)^2\times a_i \times b_\) 是否為 0 即可。

將完全平方拆開,再把 a 翻轉一下就可以 fft 算了。

#include #include #include #include using namespace std;

#define double long double

const int maxn = 300000*4;

const double pi = acos(-1);

const double eps = 0.5;

struct complex

complex(double _r, double _i) : r(_r), i(_i) {}

friend complex operator + (complex a, complex b)

friend complex operator - (complex a, complex b)

friend complex operator * (complex a, complex b)

friend complex operator / (complex a, double k)

};void fft(complex *a, int n, int type)

for(int s=2;s<=n;s<<=1) {

int t = (s >> 1);

complex u = complex(cos(type*2*pi/s), sin(type*2*pi/s));

for(int j=0;jans;

int main() {

int m, n; scanf("%d%d", &m, &n);

scanf("%s%s", sa, sb);

for(int i=0;ifft 一大缺點就是精度損失比較大,eps 太小就會誤判。。。

不過由於這道題 fft 出來肯定是整數,所以 eps 即使調到 0.5 也沒有啥大問題。

感覺匹配問題如果常規字串演算法不能做,往往就可以轉成卷積然後 fft 做。

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...