佩雷克很可能在下面的比賽中得到高分(當然,也有可能是低分)。在這個比賽中,人們被要求針對一個主題寫出甚至是意味深長的文章,並且讓一個給定的“單詞”出現次數儘量少。我們的任務是給評委會編寫一個程式來數單詞出現了幾次,用以得出參賽者最終的排名。參賽者經常會寫一長串廢話,例如500000個連續的‘T’。並且他們不用空格。
因此我們想要儘快找到一個單詞出現的頻數,即一個給定的字串在文章中出現了幾次。更加正式地,給出字母表{'A','B','C',...,'Z'}和兩個僅有字母表中字母組成的有限字串:單詞W和文章T,找到W在T中出現的次數。這裡“出現”意味著W中所有的連續字元都必須對應T中的連續字元。T中出現的兩個W可能會部分重疊。
輸入格式
輸入包含多組資料。
輸入檔案的第一行有一個整數,代表資料組數。接下來是這些資料,以如下格式給出:
第一行是單詞W,一個由{'A','B','C',...,'Z'}中字母組成的字串,保證1<=|W|<=10000(|W|代表字串W的長度)
第二行是文章T,一個由{'A','B','C',...,'Z'}中字母組成的字串,保證|W|<=|T|<=1000000。
輸出格式
對每組資料輸出一行一個整數,即W在T中出現的次數。
樣例
樣例輸入
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
樣例輸出
1
3
0
單查詢會T
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
ull mod=1234567891;
int prime=97;
int n;
ull a;
string s1,s2;
int shash(const string s){
int res=0;
int len=s.length();
for(int i=0;i<len;i++){
res=((ll)res*prime+s[i])%mod;
}
return res;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int ans=0;
cin>>s1>>s2;
int num=shash(s1),len1=s1.length(),len2=s2.length();
for(int i=0;i<len2-len1+1;i++){
string s3;
for(int j=i;j<=i+len1-1;j++){
s3+=s2[j];
}
if(shash(s3)==num){
ans++;
}
}
cout<<ans<<endl;
}
}
後面看了題解,公式看不懂:
令\(f_i(s)\)表示f(s[1…i])的雜湊值
所以會有\(f_i(s)=s[1]*base^{i-1}+s[2]*base^{i-2}+…+s[i]\)
所以得出
\(f(s[l…r])=f_r(s)-f_{l-1}(s)*base^{r-l+1}\)
感覺還是看圖明白
所以思路就是預處理base的n次方,第二個串1~n的雜湊值,透過上面公式求出來與第一個串長度相同的子串的雜湊值
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
ull mod=1234567891;
int prime=97;
int n;
ull a;
char s1[1200000],s2[1200000];
ull base[1200010];
ull num2[1200010];
ull check(int l,int r){
return (ull)num2[r]-base[r-l+1]*num2[l-1];
}
int main(){
cin>>n;
base[0]=1;
for(int i=1;i<=1000000;i++) base[i]=base[i-1]*prime;
for(int i=1;i<=n;i++){
int ans=0;
scanf("%s%s",s1+1,s2+1);
int len1=strlen(s1+1),len2=strlen(s2+1);
ull num=0;
for(int j=1;j<=len1;j++){
num=num*prime+s1[j];
}
for(int j=1;j<=len2;j++){
num2[j]=num2[j-1]*prime+s2[j];
}
for(int j=1;j<=len2-len1+1;++j){
if(check(j,j+len1-1)==num) ans++;
}
cout<<ans<<endl;
}
}