[Hash]P1470 [USACO2.3] 最长前缀 Longest Prefix 题解
这不就是哈希板子吗?
就是由于你串的数量很少,因此完全可以 \(O(\lvert S \rvert N)\) 做, \(N\) 是串的数量。
直接算一下匹配串的哈希值,然后枚举模式串的每一位查前面能不能接上就行。最后答案就是最后那个能接上的位置。细节也没什么问题。
#include <bits/stdc++.h>
namespace Main {
constexpr int M = 2e5 + 7;
constexpr int N = 205;
constexpr int B = 131;
using namespace std;
unsigned long long num[N] , Pow[M] = {1} , hum[M];
int ans , cnt = 0 , n , siz[N] , dp[M] = {1}; string p , s[N];
static inline unsigned long long process(string S) {
unsigned long long res = 0; int len = S.size();
for(register int i = 0; i < len; ++i) {
res = (res * B + (unsigned long long)(S[i]));
} return res;
}
static inline unsigned long long gt(int l , int r) {
return (hum[r] - hum[l - 1] * Pow[r - l + 1]);
}
static inline void Process() {
for(register int i = 1; i <= cnt; ++i) {
num[i] = process(s[i]); // 处理匹配串的哈希值
}
}
static inline void P() {
for(register int i = 1; i <= n; ++i) {
Pow[i] = Pow[i - 1] * B;
hum[i] = hum[i - 1] * B + (unsigned long long)(p[i]);
}
}
static void _() {
for(cnt = 1; cnt <= N; ++cnt) {
cin >> s[cnt]; siz[cnt] = s[cnt].size();
if(s[cnt] == ".") {
--cnt; break;
}
}
Process(); char c;
for(string l; cin >> l; p += l) {}
p = " " + p;
n = p.size(); P();
for(register int i = 1; i <= n; ++i) {
for(register int j = 1; j <= cnt; ++j) {
if(dp[i - siz[j]] && gt(i - siz[j] + 1 , i) == num[j]) {
dp[i] = 1; break;
}
}
if(dp[i]) {ans = i;}
}
cout << ans;
}
}
signed int main() {Main :: _(); return 0;}