字串(hash演算法完成)
阿新 • • 發佈:2020-12-28
字串(hash演算法完成)
題目描述
給一個字串T,問在字串T 中可以包含最多多少個不重疊的字串S。
字串中的每個字元為小寫或者大寫字母。
輸入
第一行輸入一個字串S。
第二行輸入一個字串T。
輸出
輸出一行,包括一個整數表示答案。
樣例輸入
aba
abababa
樣例輸出
2
提示
【資料範圍】:
20%的資料,1<=字串T 長度<=20000, 1<=字串S 長度<=100;
100%的資料,1<=字串T 長度<=1000000, 1<=字串S 長度<=100000。
題目思路
初看題目,發現可以用暴力,就是可以先用find函式找子串,再用erase刪除(不懂出門左轉找度娘),但只能騙20%分數,find函式用O(n),earse函式也要用O(n),暴力分分鐘TLE。那如何解決,這裡就採用了hash演算法,求子串的hash值,再進行匹配,匹配成功的記錄,然後輸出
原始碼
#include<bits/stdc++.h> //萬能頭,不多加解釋 using namespace std; string s,st; const long long p=29,mod1=1e9+7,mod2=1e9+9;//提醒:這裡p,mod1最好用質數,否則在轉換hash值時可能會因為出現公因數而轉換失誤,mod1要開大一點,否則也會容易翻車 long long hash1[1000007],sh,l,pow1=1,sum=0,ha1,ha2,hash2[1000009];//pow1記得1,否則平方時有可能爆0 void hs() { long long l=s.size(); for(int i=0;i<s.size();i++) sh=(sh*p%mod1+s[i]%mod1)%mod1;//用字首和和進位制轉換來轉換子串hash for(int i=1;i<=st.size();i++) { hash1[i]=(hash1[i-1]*p%mod1+st[i-1])%mod1; hash2[i]=(hash2[i-1]*p%mod2+st[i-1])%mod2;//同上,求長串hash } for(int i=1;i<=l;i++) pow1=pow1*p%mod1;//求平方,可以轉換為((pow1%mod1)*p)%mod1或((pow1%mod1)*(p%mod1))%mod1,這2個不容易TLE,pow也勉強,但容易TLE for(int i=l;i<=st.size();) { ha1=(hash1[i]-(hash1[i-l]*pow1)%mod1+mod1)%mod1; ha2=(hash2[i]-(hash2[i-l]*pow1)%mod2+mod2)%mod2;//當前這一長串的子串的子串字首和 if(ha1==sh && ha2==sh) { i+=l;//跳過這一子串,否則會造成重複 sum++; } else i++; } } int main() { getline(cin,s); getline(cin,st);//cin也可 hs(); cout<<sum; return 0;//完結撒花 }
碼後反思
這題也算是一個小毒瘤了,首先在判斷子串是否相符的那一處for的範圍卡了很久,但也沒有拿滿,發現原來就只是mod1定義太小,容易重複。
擴充套件
如果覺得看懂了,出門右轉
題目與這題很像,但很多坑