Power Strings P5019
阿新 • • 發佈:2018-11-30
Description
給定若干長度小於等於1000000000的字串,詢問每個字串最多由多少個相同的子串重複連線而成(迴圈節),例如ababab,最多由3個ab連線而成
Input
若干行,每行一個字串。最後一行是一個"."點號,作為輸入的結尾
Output
對應輸入的每行,計算最多有多少個相同子串連線而成
Hint
This problem has huge input, use scanf instead of cin to avoid Time Limit Exceed.
Solution
列舉從1到m的子串長度並且用cnt來記錄出現的次數肯定要超時,因為是O(m^2)的時間複雜度,而m是百萬級別的資料。既然出現了迴圈節,那麼迴圈的次數,也就是出現的次數=m/迴圈節的長度,那麼迴圈節就一定是m的因數,用ins陣列來存放m的所有因數。然後setb和sethash,定義findhash為bool型別返回一個迴圈節是否跟S串匹配,如果匹配,那麼就輸出答案,如果沒有就繼續找。由於這個是單調的,子串長度越小那麼答案就越大,所以從小到大找只要findhash返回true就輸出m/ins[i]。
注意事項:
1、不用把陣列清零了會把power清掉。。。
2、if語句下面只管一句所以不要忘了{}。。。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define maxn 1000005 #define inf 0x3f3f3f3f #define ull unsigned long long using namespace std; char S[maxn]; ull power[maxn],sumb,ha[maxn]; int ins[maxn]; int m,cnt; void setins(){ cnt=0; m=strlen(S+1); for(int k=1;k<=sqrt(m);k++){ if(k*(m/k)==m){ ins[++cnt]=k; ins[++cnt]=m/k; } } sort(ins+1,ins+1+cnt); } void setb(int b){ power[0]=1; for(int i=1;i<=m;i++){ power[i]=power[i-1]*b; } } void sethash(int b){ ha[0]=0; for(int i=1;i<=m;i++){ ha[i]=ha[i-1]*b+S[i]-'A'+1; } } bool findhash(int i){ int len=ins[i]; for(int j=1;j+len-1<=m;j+=len){ if(ha[len]!=ha[j+len-1]-ha[j-1]*power[len])return false; } return true; } int main(){ while(1){ scanf("%s",S+1); if(S[1]=='.')break; else{ setins(); setb(53); sethash(53); for(int i=1;i<=cnt;i++){ if(!findhash(i))continue; else{ printf("%d\n",m/ins[i]); break; } } } } return 0; }