hdu 4821 ||2013年長春站J題 字串雜湊+map的應用

life4711發表於2014-08-26

http://acm.hdu.edu.cn/showproblem.php?pid=4821



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
題目大意:

                  給定一個字串在其中找出子串長度 m*l,並且該字串可分為m段每段長度均為l,求有多少個這樣的子串。

解題思路:

                 利用雜湊算出每個子串的雜湊值,利用map,注意不能直接暴力一遍,會超時,技巧在程式碼。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <map>
//#define debug
using namespace std;

typedef unsigned long long ULL;

const int SIZE = 100003;
const int SEED = 13331;
const int MAX_N = 110000 + 10;
char s[MAX_N];
struct HASH{
    ULL H[MAX_N];
    ULL XL[MAX_N];
    int len;
    HASH(){}
    void build(char *s){
        len=strlen(s);
        H[len]=0;
        XL[0]=1;
        for (int i=len-1;i>=0;i--){
            H[i]=H[i+1]*SEED+s[i];
            XL[len-i]=XL[len-i-1]*SEED;
        }
    }
    ULL hash(int i,int L){
        return H[i]-H[i+L]*XL[L];
    }
}hs;
char a[100005];
int n,m,cnt;
map<ULL,int> p;
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        scanf("%s",a);
        hs.build(a);
        int len=strlen(a);
        cnt=0;
        for(int i=0;i<m&&i<=(len-n*m);i++)
        {
            p.clear();
            for(int j=i;j<i+n*m;j+=m)
                p[hs.hash(j,m)]++;
            if(p.size()==n)
                cnt++;
            for(int j=i+n*m;j<=len-m;j+=m)
            {
                p[hs.hash(j-n*m,m)]--;
                if(p[hs.hash(j-m*n,m)]==0)
                    p.erase(hs.hash(j-m*n,m));
                p[hs.hash(j,m)]++;
                if(p.size()==n)
                    cnt++;
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}


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

相關文章