hdu 4821

String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1410    Accepted Submission(s): 414

Problem Description

Given a string S and two integers L and M, we consider a substring of S as “recoverable” if and only if
  (i) It is of length M*L;
  (ii) It can be constructed by concatenating M “diversified” substrings of S, where each of these substrings has length L; two strings are considered as “diversified” if they don’t have the same character for every position.

Two substrings of S are considered as “different” if they are cut from different part of S. For example, string "aa" has 3 different substrings "aa", "a" and "a".

Your task is to calculate the number of different “recoverable” substrings of S.

Input

The input contains multiple test cases, proceeding to the End of File.

The first line of each test case has two space-separated integers M and L.

The second ine of each test case has a string S, which consists of only lowercase letters.

The length of S is not larger than 10^5, and 1 ≤ M * L ≤ the length of S.

Output

For each test case, output the answer in a single line.

Sample Input

3 3

abcabcbcaabc

Sample Output

2

题目意思:问存在多少个子串,长度为n*l,而且这个子串由n个不同的 且长度都为l的串构成

直接hash长度为l的串就可以了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string.h>
 4 #include<vector>
 5 #include<algorithm>
 6 #include<map>
 7 using namespace std;
 8 typedef unsigned long long ull;
 9 #define mmax 100000+10
10 ull base[mmax],seed=131,ansx[mmax],ansy[mmax],aans[mmax];
11 bool vit[mmax],vit2[mmax];
12 map<ull,int>to;
13 int n,m;
14 char p[mmax];
15 int main(){
16     base[0]=1;
17     for(int i=1;i<=100000;i++) base[i]=base[i-1]*seed;
18     while(cin>>n>>m){
19         scanf("%s",p);
20         int len=strlen(p),tmp=n*m,id=0;
21         memset(ansx,0,sizeof(ansx));
22         for(int i=0;i<m;i++)
23         ansx[0]=ansx[0]*seed+p[i];
24         for(int i=m;i<len;i++) ansx[i-m+1]=ansx[i-m]*seed-p[i-m]*base[m]+p[i];
25         memset(ansy,0,sizeof(ansy));
26         for(int i=0;i<tmp;i++)
27         ansy[0]=ansy[0]*seed+p[i];
28         for(int i=tmp;i<len;i++) ansy[i-tmp+1]=ansy[i-tmp]*seed-p[i-tmp]*base[tmp]+p[i];
29         memset(aans,0,sizeof(aans));
30         for(int i=0;i<m;i++){
31             to.clear();
32             int first=i;
33             for(int j=i,num=0;j<len+m;j+=m,num++){
34                 if(num>=n){
35                     if(to.size()==n) {
36                         aans[id++]=ansy[first];
37                     }
38                     to[ansx[first]]--;
39                     if(!to[ansx[first]]) to.erase(ansx[first]);
40                     first+=m;
41                 }
42                 to[ansx[j]]++;
43             }
44         }
45         sort(aans,aans+id);
46 //        for(int i=0;i<id;i++) cout<<aans[i]<<" ";
47 //        cout<<endl;
48         if(id==0){
49             cout<<0<<endl;
50             continue;
51         }
52         int sum=0;
53         for(int i=0;i<id;i++){
54             if(aans[i]) {sum++;continue;}
55
56         }
57         cout<<sum<<endl;
58     }
59 }
时间: 2024-08-27 05:28:27

hdu 4821的相关文章

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 4821 (hash)

这道题最重要的不仅是hash这种算法,更要学会利用好STL中的<map>才行. 将连续的L个字符经过hash赋值,最后线性判断.其中的判断步骤用到了map的插入特性. #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <map> using namespace std; #define maxn 500010 #

2013 Asia Regional Changchun I 题,HDU(4821),Hash

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4821 解题报告:搞了很久,总算搞出来了,还是参考了一下网上的解法,的确很巧,和上次湘潭的比赛中的一个求平方和的题目思路很类似. 首先说一下hash,简单来说就是y = hash(x),有很多函数,可以参考这里:https://www.byvoid.com/blog/string-hash-compare/ 然后,我用的是这个:写法简单,而且重复的可能较小. // BKDR Hash Fu

[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 字符串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 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

题目大意: 希望找到连续的长为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 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(注意要加一,因为不