[字符串hash] hdu 4821 String

题意:

给你M,L,再给一个串str

任意截取M*L长度的连续子串

再把这个子串分成M份长度为L的连续串

使得这M份互不相同

问有几种截取方法

思路:

考虑到子串是否相等,就运用字符串hash

用到map判重和割补的办法优化

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"map"
#include"vector"
#include"string"
#define inf 0x7fffffff
#include"iostream"
using namespace std;
#define ll unsigned __int64
const ll maxn=100100;
ll hash[maxn],base[maxn],cnt[maxn*10];
char s[maxn];
void init(ll len)
{
    ll seed=131;
    hash[0]=0;
    base[0]=1;
    for(ll i=1; i<=len; i++)
    {
        hash[i]=hash[i-1]*seed+s[i];
        base[i]=base[i-1]*seed;
    }
}
ll gethash(ll L,ll R)
{
    return hash[R]-hash[L-1]*base[R-L+1];
}
int main()
{
    ll m,l;
    while(scanf("%I64u%I64u",&m,&l)!=-1)
    {
        ll ans=0,lit=m*l;
        scanf("%s",s+1);
        ll len=strlen(s+1);
        init(len);
        for(ll i=1; i<=l; i++)
        {
            map<ll,ll>mark;
            ll sum=1,ssb=0;
            for(ll j=i; j<=i+lit-1; j+=l)     //以首开头的 先取第一个M份
            {
                ll tep=gethash(j,j+l-1);
                if(mark[tep]==0)
                {
                    mark[tep]=sum++;
                    ssb++;
                    cnt[mark[tep]]=0;
                }
                cnt[mark[tep]]++;
            }
            if(ssb==m) ans++;
            for(ll j=i+lit; j+l-1<=len; j+=l)
            {
                ll tep=gethash(j-lit,j-lit+l-1);
                cnt[mark[tep]]--;                //删掉第一份中长度L的串
                if(cnt[mark[tep]]==0)
                {
                    ssb--;
                    mark[tep]=0;
                }
                tep=gethash(j,j+l-1);            //加上后面长度为L的串
                if(mark[tep]==0)
                {
                    mark[tep]=sum++;
                    ssb++;
                    cnt[mark[tep]]=0;
                }
                cnt[mark[tep]]++;
                if(ssb==m) ans++;
            }
        }
        printf("%I64u\n",ans);
    }
    return 0;
}
时间: 2024-07-29 03:13:28

[字符串hash] hdu 4821 String的相关文章

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 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 字符串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 (字符串哈希)

题目链接: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

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

hdu 3973 字符串hash+线段树

http://acm.hdu.edu.cn/showproblem.php?pid=3973 Problem Description You are given some words {Wi}. Then our stupid AC will give you a very long string S. AC is stupid and always wants to know whether one substring from S exists in the given words {Wi}