[1455]Oulipo 解題報告 (哈希)


2018-10-26 20:25:42


 

1455:【例題1】Oulipo

【題目描述】

給出兩個字符串s1,s2((只有大寫字母),求s1在s2中出現多少次。

例如:s1="ABA",s2="ABAABA",答案為2。

【輸入】

輸入T組數據,每組數據輸出結果。

【輸出】

如題述。

【輸入樣例】

3
BAPC
BAPC
AZA
AZAAZAAZA
VEEDI
AVERDXIVYERDLAN

【輸出樣例】

1
3
0

【提示】

1≤s1的長度 ≤104​​ ,1≤s2的長度 ≤106​​ 。


【題目大意】

其實這道題就是一個哈希的模板題吧,然后我想寫解題報告加深一下印象。

【思路】

我的思路就是哈希的思路(哈哈),然后具體說一下哈希的算法是怎么樣的。

其實,哈希的功能就是解決像這道題目類型的,在一個字符串s2中匹配s1(找出現的位置或者出現的次數)

哈希的大體思想就是將每一段字符串或者大數據用變量直接來表示,這樣只要直接比較兩段字符串的哈希值

就可以直接判斷這兩段字符串或者大數據是不是相等。

第一個問題,怎么用變量表達字符串呢?

我們事先選一個合適的互質的b和h兩個值(b<h),則字符串C=C1C2C3...Cm我們定義的哈希值是:

H[m]=(C1bm-1+C2bm-2+...+Cmb0)%h

那其實只要遞推一下就可以解決了H[k]=H[k-1]*b+c[k];(暫不考慮%的東西)

舉個例子:C=“ABCD”

H[1]=1;

H[2]=1*b+2;

H[3]=1*b2+2*b+3;

H[4]=1*b3+2*b2+3*b+4;

然后對於某一段字符串的哈希值,C‘=“BC”

H[C']=H[3]-H[1]*b2

就是對於C'=Ck+1Ck+2...Ck+n

H[C']=H[k+n]-H[k]*bn

第二個問題,怎么很好很快的算出bn的值?

其實只要先預處理一下就好了,power[n]=power[n-1]*b

第三個問題,怎么比較?

枚舉s2從0開始到m-n(m表示s2的長度,n表示s1的長度),如果哈希值相等則這兩段字符串相等。

然后代碼插上!


#include<bits/stdc++.h>
using namespace std;

int T;
int n,m;
int ans;
char s1[10000+10],s2[1000000+10];
unsigned long long power[1000000+10];
unsigned long long H[1000000+10];
unsigned long long s,b=27,h=1<<31;
//unsigned long long 這是比long long還大的定義,但沒有負值

int main()
{
    power[0]=1;
    for(int i=1;i<=1000000;i++)
    power[i]=power[i-1]*b;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",s1+1,s2+1);
        n=strlen(s1+1);m=strlen(s2+1);
        H[0]=0;
        for(int i=1;i<=m;i++) H[i]=(H[i-1]*b+(unsigned long long)(s2[i]-'A'+1))%h;//預處理出s2的每個字符前的哈希值
        s=0;
        for(int i=1;i<=n;i++) s=(s*b+(unsigned long long)(s1[i]-'A'+1))%h;//算出s1的哈希值
        ans=0;
        //for(int i=1;i<=m;i++)
        //cout<<H[i]<<endl;
        //cout<<s<<endl;
        for(int i=0;i<=m-n;i++)
         if(s==H[i+n]-H[i]*power[n]) ans++;
        printf("%d\n",ans);
    }
    return 0;
}

 


免責聲明!

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



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