hdu 4821 String(字符串hash)

题目链接:hdu 4821 String

题意:

给你一个字符串,问你有多少子串,满足长度为m*len,并且这个子串能分成m个len长度的不同串。

题解:

BKDRhash+map来判重。注意的是要以len长分类来扫,这样才不会超时。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 typedef unsigned long long ull;
 5 const int str_len=1e5+7;
 6 struct string_hash
 7 {
 8     const static int seed=31;
 9     int len;
10     ull h[str_len],b[str_len];
11     inline int idx(char x)
12     {
13         return x-‘a‘+1;
14     }
15     void init()
16     {
17         h[0]=0,b[0]=1;
18         F(i,1,str_len-1)b[i]=b[i-1]*seed;
19     }
20     void ins(char *s)//从1开始。
21     {
22         len=strlen(s+1);
23         F(i,1,len)h[i]=h[i-1]*seed+idx(s[i]);
24     }
25     inline ull ask(int l,int r){return h[r]-b[r-l+1]*h[l-1];}//区间段hash值
26 }str;
27
28 int m,l,ans;
29 char s[str_len];
30 map<ull,int>cnt;
31 int main()
32 {
33     str.init();
34     while(~scanf("%d%d",&m,&l))
35     {
36         scanf("%s",s+1);
37         str.ins(s),ans=0;
38         for(int i=1;i<=l&&i+m*l<=str.len;i++)
39         {
40             cnt.clear();
41             for(int j=i;j<i+m*l;j+=l)cnt[str.ask(j,j+l-1)]++;
42             ans+=(cnt.size()==m);
43             for(int j=i+m*l;j+l-1<=str.len;j+=l)
44             {
45                 cnt[str.ask(j,j+l-1)]++;
46                 ull tmp;
47                 cnt[tmp=str.ask(j-m*l,j-m*l+l-1)]--;
48                 if(cnt[tmp]==0)cnt.erase(tmp);
49                 ans+=(cnt.size()==m);
50             }
51         }
52         printf("%d\n",ans);
53     }
54     return 0;
55 }

时间: 2024-07-30 10:18:26

hdu 4821 String(字符串hash)的相关文章

HDU 4821 String 字符串hash(水

题意: 给定整数M L 一个字符串s 我们定义一个子串为"好"串 iff 1.长度为 M*L 2.把这个好串分成M段,每段长度为L,且每段各不相同. 且我们得到的这些好串不重复计算(即把这些好串去重) 问有几个好串 #include <stdio.h> #include <cstring> #include <iostream> #include <map> using namespace std; typedef unsigned lo

HDU 4821 String (HASH)

题意:给你一串字符串s,再给你两个数字m l,问你s中可以分出多少个长度为m*l的子串,并且子串分成m个长度为l的串每个都不完全相同 首先使用BKDRHash方法把每个长度为l的子串预处理成一个数字,接着根据题意直接map判重 BKDRHash:一种常用字符串hash,hash简单来说就是把一串字符串通过一些转化成为一个数字,并保证相同字符串转化的数字一样,不相同字符串转化的数字一定不一样.方法就是hash[i]=hash[i-1]*seed(进制)+str[i]-'a'+1(注意要加一,因为不

[HDU 4821] String (字符串哈希)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意:给你M,L两个字母,问你给定字串里不含M个长度为L的两两相同的子串有多少个? 哈希+枚举 我就是不会枚举这样的,这次涨姿势了. 每次枚举起点,然后就能枚举全部的. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #inclu

[字符串hash] hdu 4821 String

题意: 给你M,L,再给一个串str 任意截取M*L长度的连续子串 再把这个子串分成M份长度为L的连续串 使得这M份互不相同 问有几种截取方法 思路: 考虑到子串是否相等,就运用字符串hash 用到map判重和割补的办法优化 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #in

hdu4821 String 字符串hash(bkdrhash)

题意:给定m,l,一个字符串str. 我们定义一个子串为"recoverable"串 当 1.长度为 M*L 2.把这个好串分成M段,每段长度为L,且每段各不相同. 求"recoverable"串的个数,串相同位置不同也算不同. 思路:预处理数组hash,hash[i]表示从i位置到尾的字符串hash值.这里数组为unsigned long long型,因为可以自动取模.然后枚举 前l个位置,每次向后翻滚(将前一个长度为l的段hash值从map中去除,将翻滚后新出现

HDU 4821 String

String 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意: 给定一个字符串(最长10^5).从中选一个长度为 m * l 的子串,要求该子串能拆分为m个长度为 l 的一一不同的串.问有多少种取法. 解题思路: 比赛的时候,没有将串按照模 l 之后分类,导致TLE.. 字符串的哈希为:a[i] = a[i+1] * seek + str[i] - 'a' + 1; 那么j到j+len之间的字符串的哈希值是:a[j] - a[j+

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

http://acm.hdu.edu.cn/showproblem.php?pid=4821 昨晚卡了非常久,開始TLE,然后优化了之后,由于几个地方变量写混.一直狂WA.搞得我昨晚都失眠了,,. 这几次hash军写错的变量--tmp=(j==m-1)?ah[j]:(ah[j]-ah[j-m]*base[m]);  外层循环变量是i,我写的字符串hash的几题都写成tmp=(i==0)? ah[j]:(ah[j]-ah[j-m]*base[m]); 二逼啊 题目大意: 给定一个字符串(最长10^

HDU 4821 字符串hash

题目大意: 希望找到连续的长为m*l的子串,使得m个l长的子串每一个都不一样,问能找到多少个这样的子串 简单的字符串hash,提前预处理出每一个长度为l的字符串的hash值 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <map> 6 #include <set> 7 8 using na

HDU 4821 杭州现场赛:每个片段字符串哈希比较

I - String Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4821 Description Given a string S and two integers L and M, we consider a substring of S as "recoverable" if and only if (i) I