牛客網 P15253 白兔的字串 (字串雜湊)
阿新 • • 發佈:2020-11-19
題目連結:https://ac.nowcoder.com/acm/problem/15253
詢問迴圈同構是否相同,那就將原串所有的迴圈同構串的雜湊值表示出來,
迴圈同構相當於是一個環,所以化環為鏈,長度加倍,然後依次處理即可
\(H[i]\) 表示字首 \(i\) 的雜湊值,則字串 \([l,r]\) 的雜湊值即為 \(H[r] - H[l - 1] * P[r - l + 1]\) ,
其中 \(p[i]\) 表示 \(base\) 的 \(i\) 次冪
對每個詢問串遍歷檢查即可
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #include<stack> #include<queue> #include<map> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 2000010; const ull base = 131; int n, L; ull p[maxn], f[maxn]; char A[maxn], C[maxn]; char S[maxn]; ull v[maxn]; int tot = 0; inline void solve(){ scanf("%s", S + 1); int len = strlen(S + 1); for(int i = 1 ; i <= len ; ++i){ f[i] = f[i - 1] * base + S[i] - 'a' + 1; } ll ans = 0; for(int i = 1; i + L - 1 <= len ; ++i){ ull val = f[i + L - 1] - f[i - 1] * p[L]; int p = lower_bound(v + 1, v + 1 + tot, val) - v; if(v[p] == val) ++ans; } cout << ans << endl; } ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; } int main(){ p[0] = 1; for(int i = 1 ; i <= 2000000 ; ++i){ p[i] = p[i - 1] * base; } scanf("%s", A + 1); n = read(); L = strlen(A + 1); for(int i = 1 ; i < L ; ++i) A[i + L] = A[i]; for(int i = 1 ; i <= L + L ; ++i){ f[i] = f[i - 1] * base + A[i] - 'a' + 1; } for(int i = 1 ; i <= L ; ++i){ ull val = f[i + L - 1] - f[i - 1] * p[L]; v[++tot] = val; } sort(v + 1, v + 1 + tot); for(int i = 1 ; i <= n ; ++i){ solve(); } return 0; }