洛谷P4173 殘缺的字串

2022-06-13 14:36:11 字數 1386 閱讀 5043

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

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

\(m\leq n\leq 3\times 10^5\)。

給每乙個字母乙個權值,那麼乙個區間 \([l,r]\) 如果可以匹配,那麼必然滿足

\[\sum^_a_ib_i(a_i-b_i)^2=0

\]設 \(f_i\) 表示位置 \(i\) 的權值(也就是如果上式 \(l=i,r=i+n-1\)),那麼有

\[f_i=\sum^_a_jb_(a_j-b_)^2

\]不難想到把 \(a\) 逆序,拆開括號,並且把 \(a_\) 設為 \(0\),

\[f_=\sum^_a_^3b_+\sum^_a_b^3_-\sum^_2a_^2b_^2

\]跑三次 fft 即可。常數較大,開 o2 才過。

時間複雜度 \(o(n\log n)\)。

#include #define cp complexusing namespace std;

const int n=1050000;

const double eps=0.5,pi=acos(-1);

int n,m,lim,a[n],b[n],rev[n];

cp f[n],g[n],h[3][n];

char s[n],t[n];

queueqans;

int c[n];

void fft(cp *f,int tag)

fft(f,1); fft(g,1);

for (int i=0;ifft(h[0],-1);

for (int i=0;ifft(f,1); fft(g,1);

for (int i=0;ifft(h[1],-1);

for (int i=0;ifft(f,1); fft(g,1);

for (int i=0;ifft(h[2],-1);

for (int i=1;i<=m-n+1;i++)

if (fabs((h[0][m+i].real()+h[1][m+i].real()-h[2][m+i].real())/lim)qans.push(i);

printf("%d\n",qans.size());

for (;qans.size();qans.pop())

printf("%d ",qans.front());

return 0;

}

洛谷 P4173 殘缺的字串

不知道xjb kmp可不可以做的說 假設下標都以0開頭 對於有一定偏移量的序列的 對應位置 匹配或者數值計算的題,這裡是有一種套路的,就是把其中乙個序列翻轉過來,然後卷積一下,所得到的新序列c的每乙個位置就包含了 所有原來一定偏移量的位置的乘積和。對於這個題,我們只需要找到一種方法,使相同的字元代表...

洛谷 P4173 殘缺的字串 FFT

給定長度為 m 的模式串和長度為 n 的目標串,兩個串都帶有萬用字元,求所有匹配的位置。fft 帶有萬用字元的字串匹配問題。設模式串為 p 目標串為 t 將兩個串的內容都根據字母先後順序對映到 1 到 26 如果不帶有萬用字元,那麼 t 以第 k 位結束的長度為 p 的子串與 p 匹配時有 sum ...

P4173 殘缺的字串 FFT

給出兩個字串 s,t 其中包含小寫字母和一些 可以匹配任何字元。求有多少個 p 使得 t s 如果不考慮 我們可以用做差法來匹配兩個字元,構造匹配函式 f x sum t i s 2 這樣若 f x 0 證明它們在位置 x 處匹配。但是現在有 也就是要跳過有 的位置,定義 的值為 0 然後改一下匹配...