POJ 1200 Crazy Search (哈希)

題目連接ios

Descriptionc++

Many people like to solve hard puzzles some of which may lead them to madness. One such puzzle could be finding a hidden prime number in a given text. Such number could be the number of different substrings of a given size that exist in the text. As you soon will discover, you really need the help of a computer and a good algorithm to solve such a puzzle.
Your task is to write a program that given the size, N, of the substring, the number of different characters that may occur in the text, NC, and the text itself, determines the number of different substrings of size N that appear in the text.app

As an example, consider N=3, NC=4 and the text "daababac". The different substrings of size 3 that can be found in this text are: "daa"; "aab"; "aba"; "bab"; "bac". Therefore, the answer should be 5.ide

Input函數

The first line of input consists of two numbers, N and NC, separated by exactly one space. This is followed by the text where the search takes place. You may assume that the maximum number of substrings formed by the possible set of characters does not exceed 16 Millions.this

Outputspa

The program should output just an integer corresponding to the number of different substrings of size N found in the given text.code

Sample Inputorm

3 4
daababacip

Sample Output

5

分析:
給定一個有nc個不一樣的字符組成的字符串,而後詢問這個字符串裏面有多少個長度爲n的不徹底相同的子串。

首先想到的就是對於這個字符串使用字符串截取函數獲取每個子串,而後利用map來判重。可是這樣的話時間會超時,轉換一下利用hash的思想來求解。

明確指出是該字符串由nc個不一樣的字符組成,咱們將這nc個字符串對應成nc進制,對應的時候與字符的ASCLL碼錶沒有關係,至於該字符第一次在字符串中出現的順序有關(固然這個能夠根據本身的習慣來定義)
例如題目上給出的:daababac
對應成 4進制後是:01121213

而後根據轉換後的進制數,將每個子串對應成一個一一對應的數字,就能夠利用hash在O(1)的時間內進行判重,會大大減小時間。

須要注意的一點就是,由於咱們是按照nc進制來求數值的,而不是習慣全部的10進制,說以應該乘上的是nc。

代碼:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int num[300];
int Hash[16000009];//hash函數
int main()
{
    int n,nc;
    string str;
    while(~scanf("%d%d",&n,&nc))
    {
        memset(Hash,0,sizeof(Hash));
        cin>>str;
        int len=str.length();
        int cnt=1;
        num[str[0]]=0;
        for(int i=1; i<len; i++) //將nc個字符轉換爲對應的nc進制的數,字母和數字是一一對應的
        {
            if(num[str[i]]==0)//只有當這個字符沒有轉換過的時候,纔將該字符對應成一個數字
            {
                num[str[i]]=cnt;
                cnt++;
            }
        }
        int ans=0,sum;
        for(int i=0; i<=len-n; i++)
        {
            sum=0;
            for(int j=i; j<i+n; j++)
            {
                sum=sum*nc+num[str[j]];//特別要注意這裏由於是nc進制的計算因此乘上的是nc,不要由於咱們習慣的十進制計算而乘上10
            }
            //這樣每個長度爲n的不一樣的子串都會惟一的對應一個數字
            if(Hash[sum]==0)
            {
                Hash[sum]=1;
                ans++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
相關文章
相關標籤/搜索