[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;}
posted @ 2025-04-21 19:18  「癔症」  阅读(32)  评论(0)    收藏  举报