【模板】字符串哈希


題目描述

如題,給定N個字符串(第i個字符串長度為Mi,字符串內包含數字、大小寫字母,大小寫敏感),請求出N個字符串中共有多少個不同的字符串。

友情提醒:如果真的想好好練習哈希的話,請自覺,否則請右轉PJ試煉場:)

輸入輸出格式

輸入格式:

 

第一行包含一個整數N,為字符串的個數。

接下來N行每行包含一個字符串,為所提供的字符串。

 

輸出格式:

 

輸出包含一行,包含一個整數,為不同的字符串個數。

 

輸入輸出樣例

輸入樣例#1:
5
abc
aaaa
abc
abcc
12345
輸出樣例#1:
4

說明

時空限制:1000ms,128M

數據規模:

對於30%的數據:N<=10,Mi≈6,Mmax<=15;

對於70%的數據:N<=1000,Mi≈100,Mmax<=150

對於100%的數據:N<=10000,Mi≈1000,Mmax<=1500

樣例說明:

樣例中第一個字符串(abc)和第三個字符串(abc)是一樣的,所以所提供字符串的集合為{aaaa,abc,abcc,12345},故共計4個不同的字符串。

Tip: 感興趣的話,你們可以先看一看以下三題:

BZOJ3097:http://www.lydsy.com/JudgeOnline/problem.php?id=3097

BZOJ3098:http://www.lydsy.com/JudgeOnline/problem.php?id=3098

BZOJ3099:http://www.lydsy.com/JudgeOnline/problem.php?id=3099

如果你仔細研究過了(或者至少仔細看過AC人數的話),我想你一定會明白字符串哈希的正確姿勢的^_^

最朴素的字符串轉化,過了80分。

代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int mod=88782431;
 5 int n,l,ans;
 6 unsigned int hash;
 7 bool v[90000000];
 8 char ch[3000];
 9 int main(){
10     scanf("%d",&n);
11     for(int i=1;i<=n;i++){
12         scanf("%s",&ch);
13         l=strlen(ch);hash=1;
14         for(int j=0;j<l;j++){
15             hash=(hash*ch[j]*2351)%mod;
16         }
17         if(!v[hash]){
18             v[hash]=1;
19             ++ans;
20         }
21     }
22     printf("%d\n",ans);
23     return 0;
24 }

結果:

#1AC2ms/102238kB #2AC3ms/102238kB#3AC2ms/19226kB#4AC16ms/102238kB

#5AC17ms/83347kB#6AC17ms/83316kB#7AC13ms/102238kB

#8WA122ms/102238kB//錯誤的答案。得分0 On line 1 column 3, read 19, expected 20.

 

#9WA122ms/102238kB//錯誤的答案。得分0 On line 1 column 4, read 1, expected 2.

#10AC122ms/102238kB

用稍正經點的hash就行。

代碼實現:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int mod=29989;
 5 unsigned int hash;
 6 int n,l,a,b,ans,v[30000];
 7 int id[10010][1510];
 8 char ch[1510];
 9 bool bj(int x,int y){
10     if(id[x][0]!=id[y][0]) return 0;
11     for(int i=id[x][0];i>id[y][0]-5;i--)//比較五個就行,多了用時多,恩,其實比較最后一個了之后再比較長度和隨機一個(稍靠后)應該就行了。
12     if(id[x][i]!=id[y][i]) return 0;
13     return 1;
14 }
15 int main(){
16     scanf("%d",&n);
17     for(int i=1;i<=n;i++){
18         scanf("%s",&ch);
19         id[i][0]=strlen(ch);hash=1;
20         for(int j=0;j<id[i][0];j++){
21             hash=(hash*ch[j]*13)%mod;
22             id[i][j+1]=hash;//把求hash的中間值存一下,其實也不用存這么多。
23         }
24         while(v[hash]){//如果hash值一樣,看看字符串是否相同。
25             if(bj(v[hash],i)) break;
26             hash++;
27         }
28         if(!v[hash]){//如果這個字符串未出現過,就放下。
29             v[hash]=i;
30             ++ans;
31         }
32     }
33     printf("%d\n",ans);
34     return 0;
35 }

hash模板題,當然用set或者map更簡單。我之所以不用,是為了給出題人個面子。(其實不會用Orz)

題目來源:洛谷


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM