NOIP2001 统计单词个数 rabin-karp哈希
来源:互联网 发布:航天税控软件 编辑:程序博客网 时间:2024/06/13 06:44
1233: NOIP2001:统计单词个数
时间限制: 0 Sec 内存限制:128 MB提交: 8 解决: 6
[上一题][提交][讨论版][状态][下一题]
题目描述
给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1< k< =40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。
单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
输入
第一行有二个正整数(p,k)
p表示字串的行数;k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1< =s< =6)
接下来的s行,每行均有一个单词。
输出
输出一个整数,即最大的个数
样例输入
1 3thisisabookyouareaoh4isaoksab
样例输出
7
提示
NOIP2001提高组第三题
我用的是主流dp,所以这里不讲dp, 讲如何处理字符串。
我用的是rabin-karp哈希
记前 i 位的哈希值 为 hx[i]
搞一个base, 我的是131
hx[i] = (hx[i-1] * base + s[i]) % mod P
P是个大素数, 我选的是1e9+7
这样我们的hx[i]就等于 s[1]*base^i-1 + s[2]*base^i-2 + ..... s[i]*base^0
我们要求l, r的哈希值, 观察一下hx[l-1] 和 hx[r]
hx[l-1] = s[1]*base^l-2 + s[2]*base^l-3 + .....s[l-1]*base^0
hx[r] = s[1]*base^r-1 + s[2]*base^r-2 + .....s[r]*base^0
我们只看s[1]的指数就行了(后面一样的)
于是我们将hx[l-1]乘上 base^r-l+1次方, 用hx[r]一减, 从s[1]到s[l-1]的值全被消掉了
我们就得到了 [l, r]的哈希值
然后就dp就行了
dp也有一个坑的地方, 因为一定要分成k份, 不能 < k份, 所以我们在 f[t][j-1] 有值的时候才转移
代码如下:
#include <cstdio>#include <string.h>#define ll long long#define min(a, b) ((a) < (b) ? (a) : (b))#define max(a, b) ((a) > (b) ? (a) : (b))#define base 131#define mod 1000000007ll hx[205], re[205], po[205], t, hav[205][205], s, l[7];int f[205][205];char a[205], b[25], c[1005];int len;ll gethash(int l, int r){ return ((hx[r] - po[r-l+1]*hx[l-1])%mod+mod) % mod;}int get(int x, int y){ int i; for(i = 1; i <= s; i++) if(gethash(x, min(y, x+l[i]-1)) == re[i]) return 1; return 0;}int main(){ int i, j, p, k, n; scanf("%d%d", &p, &k); scanf("%s", a+1); len = strlen(a+1); for(i = 2; i <= p; i++){ scanf("%s", b+1); n = strlen(b+1); for(j = len+1; j <= len+n; j++) a[j] = b[j-len]; len += n; } for(i = po[0] = 1; i <= len; i++){ po[i] = po[i-1] * base % mod; hx[i] = (hx[i-1] * base + a[i]) % mod; } scanf("%d", &s); for(i = 1; i <= s; i++){ scanf("%s", c+1); n = strlen(c+1); l[i] = n; t = 0; for(j = 1; j <= n; j++) t = (t * base + c[j]) % mod; re[i] = t; } for(i = len; i >= 1; i--){ for(j = i; j >= 1; j--){ hav[j][i] = hav[j+1][i]; hav[j][i] += get(j, i); } } for(i = 1; i <= len; i++){ f[i][1] = hav[1][i]; for(j = 2; j <= k; j++){ for(t = 1; t < i; t++){ if(f[t][j-1]) f[i][j] = max(f[i][j], f[t][j-1] + hav[t+1][i]); } } } printf("%d", f[len][k]); return 0;}
- NOIP2001 统计单词个数 rabin-karp哈希
- noip2001统计单词个数
- NOIP2001 统计单词个数
- 【NOIP2001】统计单词个数
- 【动规递推】【NOIP2001】统计单词个数
- noip2001-统计单词个数2008.11.5
- 洛谷 P1026 [NOIP2001 T3] 统计单词个数
- 洛谷P1026&NOIP2001 统计单词个数
- 【洛谷1026】【NOIP2001】统计单词个数
- RQNOJ 302 PID302 / [NOIP2001]统计单词个数(区间dp)
- ACM 94. [NOIP2001] 统计单词个数(划分dp)
- noip2001 统计单词个数 (动态规划-划分)
- noip2001 统计单词数
- 【NOIP2001提高组T3】统计单词个数-字符串上的动态规划
- vc 统计单词个数
- 统计单词个数
- 统计单词个数
- 统计单词个数
- VS2010 MFC中tab control使用方法
- 20.Struts2_主题
- java构造函数
- Pandas:将两个相同结构的DataFrame的数据合并得到一个新的Dataframe
- 第十周 【项目2
- NOIP2001 统计单词个数 rabin-karp哈希
- 【第七周】项目1-建立顺序环形队列算法库
- linux netlink机制
- libpcap详解
- nfs服务器搭建
- linux链接动态库提示某个函数找不到 undefined xxx
- 第十一周 项目1 — 图基本算法库
- 查询模块里的是类还是函数
- 欢迎使用CSDN-markdown编辑器