HDU--4821(字符串哈希)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821

用到了BKD字符串哈希的方法,一直不是很会哈希,总是用map,但是很显然,map并不是万能的。

用哈希的方法可以递推的求出所有子串的哈希值,最后用map维护答案即可;注意下long long

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<climits>
using namespace std;
typedef long long ll;
typedef unsigned long long llu;

const int maxd=1e5+5;
const int seed=31;
const int INF = 0xffffffff;
///===================
char str[maxd];
llu k[maxd],_hash[maxd];
map<llu,int> s;
int M,L;

void BKD_hash(int len)
{
    k[0]=1;
    for(int i=1; i<=L; i++)
        k[i]=k[i-1]*seed;
    for(int i=len-1; i>=0; i--)
        _hash[i]=_hash[i+1]*seed+(str[i]-'a'+1);
}

int main()
{
    while(scanf("%d%d",&M,&L)==2)
    {
        scanf("%s",str);
        int len=strlen(str),cnt=0;
        BKD_hash(len);
        for(int i=0; i<L && M*L+i<len; i++)
        {
            s.clear();
            for(int j=i; j<M*L+i; j+=L)
            {
                llu id=_hash[j]-_hash[j+L]*k[L];
                s[id]++;
            }
            if(s.size()==M) cnt++;

            for(int j=M*L+i; j<len-L+1; j+=L)
            {
                llu head=j-M*L;
                llu id=_hash[head]-_hash[head+L]*k[L];
                s[id]--;
                if(s[id]==0) s.erase(id);
                llu id2=_hash[j]-_hash[j+L]*k[L];
                s[id2]++;

                if(s.size()==M) cnt++;
            }
        }

        printf("%d\n",cnt);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 18:06:40

HDU--4821(字符串哈希)的相关文章

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 1800 字符串哈希 裸题

题意:意思是有若干个飞行员,需要在扫帚上练习飞行,每个飞行员具有不同的等级,且等级高的飞行员可以当等级低的飞行员的老师,且每个飞行员至多有且只有一个老师和学生.具有老师和学生关系的飞行员可以在同一把扫帚上练习,并且这个性质具有传递性.即比如有A,B,C,D,E五个飞行员,且等级是A>B>C>D>E,那么可以使A当B的老师,B当C的老师,E当D的老师,那么A,B,C可以在同一扫帚上练习,D,E在同一把扫帚上练习,这样需要2把扫帚,而如果是A当B的老师,B当C的老师,C当D的老师,D当

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

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 co

HDU 3973 AC&#39;s String 字符串哈希

HDU 3973 通过哈希函数将一个字符串转化为一个整数,通过特定的方式可以使得这个哈希值几乎没有冲突(这就是关键之处,几乎没有视为没有= =!, 其实也可以考虑实现哈希冲突时的处理,只是这道题没必要而已),然后使用线段树维护修改后的哈希值. 因为输入的字符串只有26个,考虑使用一个大于等于26的素数p作为进制,然后将原串转化为一个p进制的数mod 2^63(也相当于自然溢出),然后这个数存入map中,然后使用线段树维护长串区间的哈希值,hash[l, r]表示将区间[l, r]的字符串转化为p

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+

字符串哈希专题

layout: post title: 字符串哈希专题 author: "luowentaoaa" catalog: true tags: mathjax: true - 字符串 传送门 A.POJ - 1200 A - Crazy Search 摘要 哈希进制转换 题意 一个字符串分成长度为N的字串.且不同的字符不会超过NC个.问总共有多少个不同的子串 思路 以nc作为进制,把一个子串化为这个进制下的数,再用哈希判断 #include<cstdio> #include&l

洛谷——P3370 【模板】字符串哈希

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明