以一道例题为例
POJ -1200 Crazy Search
http://poj.org/problem?id=1200
题意是给出一个n, 一个m, 再给出一个字符串,询问在字符串中长度为n的不同子串个数;
m为给出的串中,不同字符的个数,emmm 没啥用;
直接上代码了
#include<iostream> #include<vector> #include<stdio.h> #include<algorithm> using namespace std; typedef unsigned long long ull; vector<ull>v; int main(){ int n, m; cin >> n >> m; string s; cin >> s; int len = s.size(); ull p = 1e9 + 9, r = 1, h = 0; for(int i = 0; i < n && i < len; i++) // 先求前k位,算出r h = h * p + s[i], r *= p; if(len >= n) // 如果原串长度大于k, 即先前求的k位是其子串, 加入集合 v.push_back(h); for(int i = n; i < len; i++) // 计算k位以后的子串, 过程即是上面的介绍。 h = h * p + s[i] - s[i - n] * r, v.push_back(h); sort(v.begin(), v.end()); // 排序为了下面的去重 v.erase(unique(v.begin(), v.end()), v.end()); // 去重 cout << v.size() << endl; // 输出大小 即是答案 return 0; }再来一道实践的, 找出模式串在文本串中出现的个数。
emmm, 听起来像kmp;
ZZULIOJ 1270: 剪花布条
http://acm.zzuli.edu.cn/problem.php?id=1270
#include<iostream> #include<vector> #include<stdio.h> #include<algorithm> using namespace std; typedef unsigned long long ull; vector<ull>v; int main(){ string s, b; while (cin >> s, s != "#") { cin >> b; int len = s.size(); int k = b.size(); int cnt = 0; ull p = 1e9 + 9, r = 1, h = 0, c = 0; for(int i = 0; i < len && i < k; i++) h = h * p + s[i], r *= p; if(len >= k) v.push_back(h); for(int i = k; i < len; i++) h = h * p + s[i] - s[i - k] * r, v.push_back(h); // 与上面的算法相同求出文本串每个位置的哈希值 for(int i = 0; i < k; i++) // 求出模式串的哈希值 c = c * p + b[i]; for(int i = 0; i < v.size(); i++) { if(v[i] == c) // 如果当前位置的哈希值等于模式串, 即是相同, cnt++, i += k - 1; // 注意这题是不能共用同一个字符, 所以i 要加上k, 后面又i++了, 所以i += k - 1; } cout << cnt << endl; v.clear(); } return 0; }看懂了可以再找几道题练练