給定長度為 \(m\) 的模式串和長度為 \(n\) 的目標串,兩個串都帶有萬用字元,求所有匹配的位置。
fft
帶有萬用字元的字串匹配問題。
設模式串為 \(p\),目標串為 \(t\),將兩個串的內容都根據字母先後順序對映到 \(1\) 到 \(26\)。
如果不帶有萬用字元,那麼 \(t\) 以第 \(k\) 位結束的長度為 \(|p|\) 的子串與 \(p\) 匹配時有
\[\sum_^ (p[i] - t[k - |p| + 1 + i])^2 = 0
\]如果帶有萬用字元,只需將上式稍微改一下就行。
讓兩個串中的所有萬用字元對映到 \(0\),設匹配結果為 \(f\),則有
\[f[i] = \sum_^ (p[i] - t[k - |p| + 1 + i])^2 \cdot p[i] \cdot t[k - |p| + 1 + i]
\]接下來翻轉 \(p\) 串 (\(fft\) 的套路),設 \(r[|p| - i - 1] = p[i]\),則有
\[f[i] = \sum_^ (r[|p| - i - 1] - t[k - |p| + 1 + i])^2 \cdot r[|p| - i - 1] \cdot t[k - |p| + 1 + i]
\]下標加起來等於 \(k\),令 \(j = |p| - i - 1\),則
\[f[i] = \sum_ (r[j] - t[i])^2 \cdot r[j] \cdot t[i]
\]展開後有
\[f[i] = \sum_ (r[j]^3t[i] + t[i]^3r[j] - 2\cdot r[j]^2t[i]^2)
\]用 \(fft\) 分別求一下卷積即可。
#include using namespace std;
const double pi = acos(-1);
const double eps = 1e-8;
typedef complexcomplex;
const int maxn = 2e6 + 10;
complex p[maxn], t[maxn];
complex a[maxn], b[maxn], c[maxn], d[maxn];
complex ans[maxn];
string str;
int m, n;
int bit = 2, rev[maxn];
void get_rev()
}void fft(complex *a, int op)
for(int mid = 1; mid < bit; mid <<= 1) }}
}int main()
cin >> str;
for(int i = 0; i < n; ++i)
get_rev();
for(int i = 0; i < bit; ++i)
fft(a, 1); fft(b, 1);
for(int i = 0; i < bit; ++i)
for(int i = 0; i < bit; ++i)
fft(a, 1); fft(b, 1);
for(int i = 0; i < bit; ++i)
for(int i = 0; i < bit; ++i)
fft(a, 1); fft(b, 1);
for(int i = 0; i < bit; ++i)
fft(ans, -1);
queueq;
for(int i = m - 1; i < n; ++i)
cout << q.size() << endl;
while(q.size())
cout << endl;
return 0;
}
洛谷 P4173 殘缺的字串
不知道xjb kmp可不可以做的說 假設下標都以0開頭 對於有一定偏移量的序列的 對應位置 匹配或者數值計算的題,這裡是有一種套路的,就是把其中乙個序列翻轉過來,然後卷積一下,所得到的新序列c的每乙個位置就包含了 所有原來一定偏移量的位置的乘積和。對於這個題,我們只需要找到一種方法,使相同的字元代表...
洛谷P4173 殘缺的字串
很久很久以前,在你剛剛學習字串匹配的時候,有兩個僅包含小寫字母的字串 a 和 b 其中 a 串長度為 m b 串長度為 n 可當你現在再次碰到這兩個串時,這兩個串已經老化了,每個串都有不同程度的殘缺。你想對這兩個串重新進行匹配,其中 a 為模板串,那麼現在問題來了,請回答,對於 b 的每乙個位置 i...
P4173 殘缺的字串 FFT
給出兩個字串 s,t 其中包含小寫字母和一些 可以匹配任何字元。求有多少個 p 使得 t s 如果不考慮 我們可以用做差法來匹配兩個字元,構造匹配函式 f x sum t i s 2 這樣若 f x 0 證明它們在位置 x 處匹配。但是現在有 也就是要跳過有 的位置,定義 的值為 0 然後改一下匹配...