HDU 4821 String 字符串hash map的妙用
来源:互联网 发布:world of goo mac 编辑:程序博客网 时间:2024/05/17 12:18
题意:给出一个字符串。求有多少个子串,长度为M*L,从前到后,分成M个长度为L的子串,每个子串都不相同。
思路:字符串hash。
因为起始位置有L种可能,我们要分别统计。利用hash后的值,我们可以判断子串是否重复。
首先,我先想到的是记录每个子串在L中情况下,离他最近的且相同的子串的位置,如果位置大于M*L,那就可以继续扩展一个长度为L的子串,当长度达到M*L的时候,我们就可以答案加1.
代码如下:
#include <cstdio>#include <algorithm>#include <cstring>#include <map>using namespace std;const int MAGIC = 233;const int MAX = 100010;unsigned int h[MAX];unsigned int base[MAX];int cnt[MAX];map<unsigned int,int> ma[MAX];char s[MAX];int M,L;inline void init_hash(char *s, unsigned int *h, int l){ h[0]= 0; for(int i = 1; i <= l; ++i) h[i] = h[i-1] * MAGIC + s[i-1]; base[0] = 1; for(int i = 1; i <= l; ++i) base[i] = base[i-1] * MAGIC;}inline unsigned int string_hash(unsigned *h, int l, int r){ return h[r] - h[l]* base[r-l];}int main(void){ //freopen("input.txt","r",stdin); while(scanf("%d %d", &M, &L) != EOF) { scanf("%s",s); int n = strlen(s); int ans = 0; init_hash(s,h,n); memset(cnt,0,sizeof(cnt)); for(int i = 0; i < L; ++i) ma[i].clear(); for(int i = 0; i < L; ++i) cnt[i] = 0; for(int i = L; i <= n; ++i){ unsigned ha = string_hash(h,i-L,i); int id = i % L; if(!ma[id].count(ha)) { cnt[i] = cnt[i-L] + L; if(cnt[i] >= M * L){ ans++; cnt[i] = M * L; } } else { if((i - ma[id][ha] > cnt[i-L])) { cnt[i] = cnt[i-L] + L; if(cnt[i] >= M * L){ ans++; cnt[i] = M * L; } } else cnt[i] = i - ma[id][ha]; } ma[id][ha] = i; } printf("%d\n",ans); } return 0;}
但是不用这么麻烦的。map既可以用来计数,也可用来判重。这样,我们直接利用每种情况下map的size的大小就行了。
代码如下:
#include <cstdio>#include <algorithm>#include <cstring>#include <map>using namespace std;const int MAGIC = 233;const int MAX = 100010;unsigned int h[MAX];unsigned int base[MAX];map<unsigned int,int> ma[MAX];char s[MAX];int M,L;inline void init_hash(char *s, unsigned int *h, int l){ h[0]= 0; for(int i = 1; i <= l; ++i) h[i] = h[i-1] * MAGIC + s[i-1]; base[0] = 1; for(int i = 1; i <= l; ++i) base[i] = base[i-1] * MAGIC;}inline unsigned int string_hash(unsigned *h, int l, int r){ return h[r] - h[l]* base[r-l];}int main(void){ //freopen("input.txt","r",stdin); while(scanf("%d %d", &M, &L) != EOF) { scanf("%s",s); int n = strlen(s); int ans = 0; init_hash(s,h,n); for(int i = 0; i < L; ++i) ma[i].clear(); for(int i = L; i <= n; ++i){ unsigned ha = string_hash(h,i-L,i); int id = i % L; ma[id][ha]++; if(ma[id].size() == M) ans++; if(i >= M * L){ int st = i - M * L; unsigned ha1 = string_hash(h,st,st+L); if(--ma[id][ha1] == 0) ma[id].erase(ha1); } } printf("%d\n",ans); } return 0;}
注意:也给自己提个醒吧,在上面的hash函数中,需要hash的字符串为左闭右开区间。切记,切记。
0 0
- HDU 4821 String 字符串hash map的妙用
- hdu 4821 String(字符串hash+map)
- [hdu 4821]String 字符串hash
- HDU 4821 String 字符串hash
- [字符串hash] hdu 4821 String
- HDU 4821 String 字符串HASH
- HDU 4821 String 字符串HASH
- hdu 4821 String 字符串hash
- hdu 4821 字符串hash + map判重
- hdu 4821 字符串hash+map判重 String (长春市赛区I题)
- hdu 4821 String(枚举 + 字符串hash)
- HDU 4821 String(字符串hash)
- HDU 4821 String 字符串hash(水
- [HDU 4821]String[字符串hash][存疑]
- hdu 4821String(字符串hash)
- HDU 4821String(字符串hash)
- hdu 1075 map 的应用可以字符串的hash
- hdu4821 String (字符串hash + map)
- Css中Position属性的含义
- tomcat自动加载问题
- servlet客户端跳转+服务器端跳转
- 前言
- Ubuntu12.0.4安装nagios3.2.3中文
- HDU 4821 String 字符串hash map的妙用
- servlet过滤器的链式处理
- tomcat数据源
- propertis文件保存异常解决方法
- libevent源码深度剖析一
- 归并排序
- smart210 linux3.0.8内核蜂鸣器pwm驱动分析
- libevent源码深度剖析二
- 腾讯百度Offer的求职经历