题目链接在本地,简化以后的题意就是在一个长度为2*n的序列中有一个长度为n的滑动窗口,问能框出来多少不同的序列。
比较典型的哈希题,跟着rainy学习了哈希的经典操作,就是设两个哈希模数,算出两个哈希值,这样两个哈希都冲突的概率是非常非常低的!
这题还需要学的就是对于滑动窗口来说哈希的写法,溢出的最高位直接按模数减掉对应位乘上次幂就行了,减到小数就加一个MOD就行。
以上两个是哈希的经典操作。
tips:查询map中是否有某个值,可以用.count()函数
1 #include "bits/stdc++.h" 2 #define mp(a,b) make_pair(a,b) 3 using namespace std; 4 typedef long long LL; 5 const int MAX=1e5+5; 6 const int MOD1=1e9+7; 7 const int MOD2=1e9+9; 8 LL n,a[MAX<<1],bas1,bas2,bas1n,bas2n,ck1,ck2,ans; 9 map <pair<LL,LL>,int> p; 10 int main(){ 11 // freopen ("a.in","r",stdin); 12 // freopen ("a.out","w",stdout); 13 LL i,j; 14 bas1=999983,bas2=999979; 15 while (scanf("%lld",&n)!=EOF){ 16 p.clear(); 17 ans=0; 18 for (i=1;i<=n;i++) scanf("%lld",&a[i]); 19 for (i=n+1;i<=2*n;i++) a[i]=a[i-n]; 20 bas1n=bas2n=1; 21 for (i=1;i<n;i++){ 22 bas1n=bas1n*bas1%MOD1; 23 bas2n=bas2n*bas2%MOD2; 24 } 25 ck1=ck2=0; 26 for (i=1;i<=n;i++){ 27 ck1=(ck1*bas1%MOD1+a[i])%MOD1; 28 ck2=(ck2*bas2%MOD2+a[i])%MOD2; 29 } 30 p[mp(ck1,ck2)]=1; 31 ans++; 32 for (i=n+1;i<2*n;i++){ 33 ck1=(((ck1-a[i-n]*bas1n%MOD1)+MOD1)*bas1%MOD1+a[i])%MOD1; 34 ck2=(((ck2-a[i-n]*bas2n%MOD2)+MOD2)*bas2%MOD2+a[i])%MOD2; 35 if (p.count(mp(ck1,ck2))==0){ 36 p[mp(ck1,ck2)]=1; 37 ans++; 38 } 39 // cout<<ck1<<' '; 40 } 41 reverse(a+1,a+2*n+1); 42 ck1=ck2=0; 43 for (i=1;i<=n;i++){ 44 ck1=(ck1*bas1%MOD1+a[i])%MOD1; 45 ck2=(ck2*bas2%MOD2+a[i])%MOD2; 46 } 47 if (p.count(mp(ck1,ck2))==0){ 48 p[mp(ck1,ck2)]=1; 49 ans++; 50 } 51 for (i=n+1;i<2*n;i++){ 52 ck1=(((ck1-a[i-n]*bas1n%MOD1)+MOD1)*bas1%MOD1+a[i])%MOD1; 53 ck2=(((ck2-a[i-n]*bas2n%MOD2)+MOD2)*bas2%MOD2+a[i])%MOD2; 54 if (p.count(mp(ck1,ck2))==0){ 55 p[mp(ck1,ck2)]=1; 56 ans++; 57 } 58 } 59 printf("%d\n",ans); 60 } 61 return 0; 62 }