依稀記得,$noip$之前的我是如此的弱小....
完全不會$kmp$的寫法,只會暴力$hash$....
大體思路為把乙個串的雜湊值拆成$26$個字母的位權
即$hash(s) = \sum\limits_ a * \sum w^i * [s[i] == a]$
通過記錄每個字母第一次出現的位置,用$26$的時間來確定$f$是什麼
然後通過確定的$f$計算出$f$是正確的時候的$hash$值,和原串的$hash$值比較
複雜度$o(26n)$
自然取模....
#include #include現在我明白了$kmp$是非常偉大的演算法....#include
#include
namespace
remoon
using
namespace
std;
using
namespace
remoon;
#define sid 500050
char s[2005000
], t[sid];
int n, m, tim, f[200
];int num[200], vis[200], nxt[200
], tot;
ull val[
200], wei[sid];
ull seed = 19260817
;inline
void
init()
tim ++;
}inline
void
solve()
if(vis[v] != tim) vis[v] =tim;
f[j] =v;
}if(!flag)
now -= s[i - m + 1] * wei[m - 1
]; now *= seed; now += s[i + 1
]; }
}int
main()
對於此題而言,考慮每個字元的上乙個字元離當前字元的距離,這可以成為乙個新串
然後比對新串即可
特別的,如果上乙個字元出現的位置超過了匹配長度,那麼我們也要視作合法
但是,我們發現這種匹配滿足有前效性,沒有後效性,因此可以用$kmp$
複雜度$o(n)$,十分的優秀
#include #include#include
#include
namespace
remoon
using
namespace
std;
using
namespace
remoon;
const
int sid = 1005000
;int
n, m;
char
s[sid], t[sid];
int lst[200
], s[sid], t[sid], nxt[sid];
inline
bool match(int x, int
y) int
main()
memset(lst,
0, sizeof
(lst));
rep(i,
1, m)
for(ri i = 2, j = 0; i <= m; i ++)
for(ri i = 1, j = 0; i <= n; i ++)
return0;
}
Bzoj4641 基因改造
給定字串s和t,可以交換任意字元,求s的哪些連續子串與t匹配 題目可以轉化為 字串匹配,匹配規則是模式串與文字串的子串不一樣的情況相同 e g31 3 21 2 13 1 e.g313 212 131 既然是檢視不一樣的情況那麼就記錄一下相同元素上一次出現的位置 老套路?然後令a i b i i a...
特殊位置kmp匹配 bzoj4641 基因改造
傳送門!將每個數變成當前位置減上一次出現的位置,用kmp kmpkm p匹配,但要注意如果當前位置減上一次出現位置的差超過了匹配長度則視為沒有出現過,要特判 include include include include include define maxn 1000005 define ll l...
BZOJ 2764 JLOI2011 基因補全
題目 題意 給定乙個長度為n的鹼基序列s和乙個長度為m的鹼基序列t,現在希望向序列t裡補一定的鹼基使得序列s和序列t配對,配對的規則是a與t配對,c與g配對,新增鹼基的位置與數量不同的方案視為不同,求不同的方案數。0n 2000 題解 可以考慮算出序列t在序列s裡匹配的本質不同方案數,利用dp可以很...