(不知道xjb kmp可不可以做的說)
(假設下標都以0開頭)
對於有一定偏移量的序列的 對應位置 匹配或者數值計算的題,這裡是有一種套路的,就是把其中乙個序列翻轉過來,然後卷積一下,所得到的新序列c的每乙個位置就包含了 所有原來一定偏移量的位置的乘積和。
對於這個題,我們只需要找到一種方法,使相同的字元代表的數乘積是乙個特殊的值,然後*可以看成0(*可以匹配任意字元),這樣使得卷積後的位置是特殊值的就可以匹配。
而且這種特殊值需要滿足: 兩個特殊值相加之後還是特殊值,兩個不是特殊值相加還不是特殊值,乙個是乙個不是相加也不是特殊值。
如果要去找到所有滿足這個性質的集合的話,貌似是比較困難的qwq,哪怕就要找乙個我也不會啊qwq
但是有一種很好的方法可以擬合這個集合,那就是設特殊值是整數,然後第乙個串裡某個字元的權值和第二個串中的這種字元的權值互為倒數。
當第乙個串中的字元權值是完全在實數域上隨機的話,那麼就幾乎可以擬合上述集合了,因為可以證明若干個隨機實數的和為整數的概率趨近於0.
介於我一直對luogu的有心理陰影,所以這裡的權值並不是隨機的,而是每個字元的編碼+2333.
(結果竟然過了2333)
/*f[i] -> 開頭的偏移量 = i-m+1 的val_sum
所以統計 f[m-1] ~ f[n-1] 即可 (對應偏移量 0 ~ n-m)
*/#include#define ll long long
#define d long double
#define e complexusing namespace std;
const d pi=acos(-1),eps=1e-9;
const int maxn=300005;
e a[maxn*4],b[maxn*4];
int r[maxn*4],n,m,n,ans,p[maxn],l;
char s[maxn],s[maxn];
inline bool isz(d x)
inline bool isl(char x)
inline void build()
inline void fft(e *c,int f)
} }if(f==-1) for(int i=0;i
}inline void solve()
int main()
洛谷P4173 殘缺的字串
很久很久以前,在你剛剛學習字串匹配的時候,有兩個僅包含小寫字母的字串 a 和 b 其中 a 串長度為 m b 串長度為 n 可當你現在再次碰到這兩個串時,這兩個串已經老化了,每個串都有不同程度的殘缺。你想對這兩個串重新進行匹配,其中 a 為模板串,那麼現在問題來了,請回答,對於 b 的每乙個位置 i...
洛谷 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 然後改一下匹配...