生活随笔
收集整理的這篇文章主要介紹了
白兔的字符串
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
鏈接:
文章目錄
時間限制:C
/C
++ 1秒,其他語言
2秒
空間限制:C
/C
++ 262144K,其他語言
524288K
64bit IO Format
: %lld
題目描述
白兔有一個字符串T。白云有若干個字符串S1,S2…Sn。
白兔想知道,對于白云的每一個字符串,它有多少個子串是和T循環(huán)同構(gòu)的。
提示:對于一個字符串a(chǎn),每次把a(bǔ)的第一個字符移動到最后一個,如果操作若干次后能夠得到字符串b,則a和b循環(huán)同構(gòu)。
所有字符都是小寫英文字母
輸入描述:
第一行一個字符串T(|T|<=10^6)
第二行一個正整數(shù)n (n<=1000)
接下來n行為S1~Sn (|S1|+|S2|+…+|Sn|<=10 ^ 7),max(|S1|,|S2|,|S3|,|S4|,…|Sn|)<=10 ^ 6
輸出描述:
輸出n行表示每個串的答案
示例1
輸入
abab
2
abababab
ababcbaba
輸出
5
2
題解:
hash題
好久沒打都忘得差不多了
講哈希的博客
根據(jù)題意,我們可以得知,要尋找與T是循環(huán)同構(gòu)的子串
那T也就相當(dāng)于是環(huán),我們拆環(huán)為鏈,長度加倍,
然后將二倍的T中每一部分取哈希,每一部分的長度就是原T的長度
然后根據(jù)大小進(jìn)行排序
輸入子串a(chǎn)后,因?yàn)槭窃谥腥∵B續(xù)子串,所以本身就是一條鏈,我們按照T的長度對a的每一部分取hash然后比較是否相等
比較大小的方法可以用二分查找,因?yàn)槲覀冎耙呀?jīng)對大小進(jìn)行排序了;也可以模擬map,直接用map會超時
代碼:
因?yàn)槲业拇a寫太亂了,找了大佬條理清晰的代碼。
并加上詳細(xì)注釋(應(yīng)該很詳細(xì)了 )
#include <bits/stdc++.h>
using namespace std
;
typedef long long ll
;
typedef unsigned long long ull
;
const int maxn
= 1e6 + 5;
ull hs
[maxn
];
ull base
[maxn
];
char T
[maxn
<<1],s
[maxn
];
int n
;
vector
<ull
> v
;
ull
gethash(int i
,int j
){return hs
[j
]-hs
[i
-1]*base
[j
-i
+1];
}
bool judge(int i
,int j
){ull x
=gethash(i
,j
);int id
=lower_bound(v
.begin(),v
.end(),x
)-v
.begin();if(id
==v
.size())return false;else return v
[id
]==x
;
}
int main(){base
[0]=1;for(int i
=1;i
<maxn
;i
++)base
[i
]=base
[i
-1]*131;cin
>>(T
+1);ll len
=strlen(T
+1);for(int i
=1;i
<=len
;i
++)T
[i
+len
]=T
[i
];for(int i
=1;i
<=2*len
;i
++)hs
[i
]=hs
[i
-1]*131+(T
[i
] - 'a' + 1);for(int i
=1;i
<=len
;i
++)v
.push_back(gethash(i
,i
+len
-1));sort(v
.begin(),v
.end());cin
>>n
;while(n
--){cin
>>(s
+1);ll lens
=strlen(s
+1);int cnt
=0;for(int i
=1;i
<=lens
;i
++)hs
[i
]=hs
[i
-1]*131+(s
[i
] - 'a' + 1);for(int i
=1;i
+len
-1<=lens
;i
++)if(judge(i
,i
+len
-1))cnt
++;cout
<<cnt
<<endl
;}return 0;
}
總結(jié)
以上是生活随笔為你收集整理的白兔的字符串的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。