这是2013年长春区域赛的铜牌题。。。然而第一次做的时候一直觉得会超时的。。最后才知道并没有想象中的那么恐怖;

这题有两个注意的地方:

(1)h[i] = h[i-1] * seed + s[i] - 'a' + 1;防止ab和aab的hash值相同;(后来感觉没必要,因为都是长度相等的串,但是长度不等的串就要注意了,所以还是写在这里吧);

(2)unsigned long long 会自动取模。所以即使乘上1e5次也不会爆orz。。这是组成原理的内容了。。我也是从别的大神那里听来的;

这到题的题意就是求有多少个连续的字子串,他由m*l个小子串组成,并且m个小子串两两互不完全相同,注意区分子串与小子串的概念;

思路是对每一个小子串赋予一个hash值,对于以ai开始的子串,如果他的小子串的hash值有m个不同值那么可以知道这个子串是符合要求的,ans++;

那么一次枚举子串的起始位置可不可以呢?可以看出肯定不行,o(n^2)的复杂度;

其实对于已经找到的一个子串,我们只需要除去他的最开头的那个小子串,加上它末尾后一个小子串,不断循环下去,就可以得到一系列的子串;

因此可以把原来的串分成l个系列,每一个系列中的子串,都是可以由第一个子串减去一个小子串,加上一个新子串得到;由此降到了o(n)的复杂度;

具体细节参考代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#define N 100005
#define lc rt<<1
#define rc rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5+;
const int seed = ; char s[maxn];
int m,l;
int next[maxn];
ull h[maxn];
ull base[maxn];
map<ull, int> mp; ull string_hash(int l, int r)
{
return h[r] - h[l-]*base[r-l+];//熟练掌握字符串哈希的写法,有点类似前缀和的思想;
} int main()
{
//freopen("in","r",stdin);
base[] = ;
for(int i = ; i < maxn; ++i) base[i] = base[i-]*seed;//每一位的权重;
while(~scanf("%d%d",&m,&l))
{
scanf("%s",s+);
int len = strlen(s+);
h[] = ;
for(int i = ; i <= len; ++i)
h[i] = h[i-]*seed + s[i] - 'a';//对整个字符串进行哈希; int ans = ;
for(int i = ; i <= l&&i + m*l<= len; ++i)//注意循环条件的判断
{
mp.clear();
for(int j = i; j < i + m*l ; j+=l)
{
ull x = string_hash(j,j+l-);
//printf("%lld ",x);
mp[x]++;
}
//printf("\n");
if(mp.size() == m) ans++;//mp自带去重,好用啊!
//printf("%d %d\n",i,ans);
for(int j = i + m*l; j + l- <= len; j += l)//细细体会。。。。去头添尾;
{
ull x = string_hash(j,j+l-);
mp[x]++;
ull y = string_hash(j-m*l,j-m*l+l-);
mp[y]--;
if(mp[y] == ) mp.erase(y);
if(mp.size() == m) ans++;
}
}
printf("%d\n",ans);
}
}

HDU4821---字符串hash,map判重的更多相关文章

  1. (通俗易懂小白入门)字符串Hash+map判重——暴力且优雅

    字符串Hash 今天我们要讲解的是用于处理字符串匹配查重的一个算法,当我们处理一些问题如给出10000个字符串输出其中不同的个数,或者给一个长度100000的字符串,找出其中相同的字符串有多少个(这样 ...

  2. hdu 4821 字符串hash+map判重 String (长春市赛区I题)

    http://acm.hdu.edu.cn/showproblem.php?pid=4821 昨晚卡了非常久,開始TLE,然后优化了之后,由于几个地方变量写混.一直狂WA.搞得我昨晚都失眠了,,. 这 ...

  3. POJ3087 Shuffle'm Up —— 打表找规律 / map判重

    题目链接:http://poj.org/problem?id=3087 Shuffle'm Up Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  4. hdu 5012 bfs --- 慎用STL 比方MAP判重

    http://acm.hdu.edu.cn/showproblem.php?pid=5012 发现一个问题 假设Sting s = '1'+'2'+'3'; s!="123"!!! ...

  5. BFS以及hash表判重的应用~

    主要还是讲下hash判重的问题吧 这道题目用的是除法求余散列方式 前几天看了下算法导论 由于我们用的是线性再寻址的方式来解决冲突问题 所以hash表的大小(余数的范围)要包含我们要求的范围 对mod的 ...

  6. Hdu 4821 (字符串hash+map)

    题目链接https://vjudge.net/problem/HDU-4821 题意:给定字符串S ,询问用几个子串满足 : 1.长度为n*len  . 2. n个子串都不相同. 题解:倒序hash将 ...

  7. 字符串hash+回文树——hdu6599

    拖了很久才补的回文树,感觉网上的博客都是一个做法..回文树统计不同种类的回文串出现次数,然后用字符串hash来判每个回文子串是否符合要求 #include<bits/stdc++.h> u ...

  8. 程序员的算法课(14)-Hash算法-对海量url判重

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  9. BFS+Hash(储存,判重) HDOJ 1067 Gap

    题目传送门 题意:一个图按照变成指定的图,问最少操作步数 分析:状态转移简单,主要是在图的存储以及判重问题,原来队列里装二维数组内存也可以,判重用神奇的hash技术 #include <bits ...

随机推荐

  1. ID3算法(决策树)

    一,预备知识: 信息量: 单个类别的信息熵: 条件信息量: 单个类别的条件熵: 信息增益: 信息熵: 条件熵:(表示分类的类,表示属性V的取值,m为属性V的取值个数,n为分类的个数) 二.算法流程: ...

  2. 【KMP】Number Sequence

    KMP算法 KMP的基处题目,数字数组的KMP算法应用. 主要是next[]数组的构造,next[]存储的是字符的当前字串,与子串前字符匹配的字符数. 移动位数 = 已匹配的字符数 - 对应的部分匹配 ...

  3. vi查找

    /pattern<Enter> :向下查找pattern匹配字符串 ?pattern<Enter>:向上查找pattern匹配字符串 使用了查找命令之后,使用如下两个键快速查找 ...

  4. (转)How to build an Apple Push Notification provider server (tutorial)

    转自:https://blog.serverdensity.com/how-to-build-an-apple-push-notification-provider-server-tutorial/ ...

  5. nexus4/5/6/7/9/10设备谷歌安卓5.1.1系统底包下载

    https://developers.google.com/android/nexus/images http://www.inexus.co/thread-18488-1-1.html

  6. Sublime Text2 按shift键选择不了的问题

    记录下来,免得以后忘了: 今天在Sublime Text 2装了一个ThinkPHP插件之后.发现按shift键+鼠标左键选择不了内容了.原因是ThinkPHP里的热键与系统的有冲突了,须要设置例如以 ...

  7. HDOJ1251-统计难题(trie树入门)

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Subm ...

  8. Linux命令之必杀绝技Vi文本编辑的使用

    vi  文本编辑器 语法:vi [参数] 文件 进入vi全屏幕编辑画面 按字母i进入[输入模式],按[ESC]转到命令行, 输入 :q可不保存退出vi :wq存盘退出vi :q!不存盘强制退出 :w ...

  9. (转)HiddenField控件的使用

    ASP.NET2.0 HiddenField控件(1)2007-05-12 23:18HiddenField控件顾名思义就是隐藏输入框的服务器控件,它能让你保存那些不需要显示在页面上的且对安全性要求不 ...

  10. T-SQL 一次插入多行数据

    使用 INSERT SELECT 向表中插入数据 --将t1中查询到的数据插入添加到t2中(t2表必须存在,且顺序.数据类型必须与t1一致) INSERT INTO t2(USERNAME,PASSW ...