HDU 4821 字符串哈希
2017-09-16 10:29
246 查看
题意:
给出m和L和一个字符串s,要求在s中找到一种子串,满足长度为m*l,且分成m段长度为l的小子串可以使得任意两个小子串不完全相同,问一共有多少个这样的子串。思路:
字符串哈希。预处理出每个长度为L的子串的哈希值,并按照其起始位置%L的结果存在L个vector里,对于每个vector只要单纯看连续m个数是否有相同的数字即可,如果没有就更新答案。
代码:
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ULL; const ULL seed = 131; const int MAXN = 1e5 + 10; int m, l; char s[MAXN]; ULL sum[MAXN], f[MAXN]; vector <ULL> vec[MAXN]; void init() { f[0] = 1; for (int i = 1; i <= 100000; i++) f[i] = f[i - 1] * seed; } int cal() { int ans = 0; for (int i = 0; i < l; i++) { int cnt = 0; if ((int)vec[i].size() < m) continue; map <ULL, int> mp; for (int j = 0; j < m; j++) { if (mp[vec[i][j]] == 1) ++cnt; ++mp[vec[i][j]]; } if (cnt == 0) ++ans; for (int j = 1; j + m <= (int)vec[i].size(); j++) { --mp[vec[i][j - 1]]; if (mp[vec[i][j - 1]] == 1) --cnt; if (mp[vec[i][j + m - 1]] == 1) ++cnt; ++mp[vec[i][j + m - 1]]; if (cnt == 0) ++ans; } } return ans; } int main() { //freopen("in.txt", "r", stdin); init(); while (scanf("%d%d", &m, &l) == 2) { scanf("%s", s + 1); int len = strlen(s + 1); for (int i = 1; i <= len; i++) { sum[i] = sum[i - 1] * seed + s[i] - 'a'; } for (int i = 0; i < l; i++) vec[i].clear(); for (int i = 1; i + l - 1 <= len; i++) { int j = i + l - 1; ULL tmp = sum[j] - sum[i - 1] * f[j - i + 1]; vec[(i - 1) % l].push_back(tmp); } printf("%d\n", cal()); } return 0; }
相关文章推荐
- hdu-4821(BKDRHash字符串哈希)
- HDU 4821 String(字符串哈希)
- hdu 4821 滑动窗口+字符串哈希
- HDU 4821 String 字符串哈希
- HDU--4821(字符串哈希)
- HDU 4821 String 字符串哈希
- [HDU 4821] String (字符串哈希)
- HDU 4821 String 解题报告(哈希)
- HDU 4821 String(字符串Hash)
- HDU - 1880 字符串哈希
- HDU 4821 (哈希)
- HDU 4622 Reincarnation (区间不相同子串个数:字符串哈希 | 后缀数组 | 后缀自动机)
- hdu 4821 String(字符串hash)
- hdu 3973 AC's String 字符串哈希处理 查询子串是否是模式串 可以修改
- HDU 4821 String 字符串HASH
- [HDU 4080] Stammering Aliens (字符串哈希+二分)
- HDU - 4821(95/600)字符串水题
- HDU 4821 字符串hash
- hdu 1228 A + B 详细题解 字符串/哈希
- HDU 4821 String 字符串HASH