UVA1401 Remember the Word 题解
考虑一个动态规划, 表示前 个字符的划分方案。枚举 ,对于 前 个字符的某个后缀,如果出现在字典里,就转移。形式化地,如果 为一个在字典的后缀,那么 。。
但直接转移是 的。发现字典每个字符串长度不超过过 ,只需要枚举位数,用哈希判断即可。不过有点卡常。
#pragma GCC optimize("-Ofast,fast-math,-inline")
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <string>
#include <algorithm>
#include <unordered_set>
using namespace std;
using ull = unsigned long long;
const int N = 3e5 + 5, M = 4005, K = 105, MOD = 20071027;
long long f[N];
string s;
int n;
string t[M];
ull hashing[N], hash2[M][K];
ull powe[N];
unordered_set<ull> st;
int main()
{
ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
int c = 0;
powe[0] = 1;
for (int i = 1; i < N; i++)
{
powe[i] = powe[i - 1] * 841;
}
while (cin >> s)
{
st.clear();
int p = s.size();
for (int i = 1; i <= p; i++)
{
hashing[i] = hashing[i - 1] * 841 + s[i - 1];
}
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> t[i];
int pp = t[i].size();
for (int j = 1; j <= pp; j++)
{
hash2[i][j] = hash2[i][j - 1] * 841 + t[i][j - 1];
}
st.insert(hash2[i][pp]);
}
f[0] = 1LL;
for (int i = 1; i <= p; i++)
{
f[i] = 0LL;
int maxn = min(i, 100);
for (int j = 1; j <= maxn; j++)
{
int l = i - j + 1, r = i;
ull subhash = hashing[r] - hashing[l - 1] * powe[r - l + 1];
if (st.count(subhash)) f[i] = (f[i] + f[l - 1]) % MOD;
}
}
cout << "Case " << ++c << ": " << f[p] << "\n";
}
return 0;
}

浙公网安备 33010602011771号