【洛谷U142342】詢問
阿新 • • 發佈:2020-11-27
題目
題目連結:https://www.luogu.com.cn/problem/U142342?contestId=37784
如果兩個字串 a 和 b,如果可以通過將 a 中的 \(26\) 種字母一一對應的替換為不重複的 \(26\) 種字母變成 b 的話,我們就稱 a 和 b 是等價的。
例如 "zzpzpt" 和 "oofofc" 是等價的,"rrrtt" 和 "ooopp" 也是等價的,而 "qqq" 和 "ppq" 就不是,"apple" 和 "abcde" 也不是。
有一個均由小寫字母構成字串 s,長度為 \(n\)。
有 \(m\) 個詢問,每個詢問給定三個數字 \(x,y,z\),詢問 s 中以 \(x\)
思路
隨便取一個字母 \(a\),在字串中如果第 \(i\) 為是字母 \(a\) 我們就設為 \(1\),否則設為 \(0\)。
那麼兩個子串等價其實就是存在一種兩兩對應的方案,且在對應的區間內他們的 \(01\) 串相同。
那麼將每個字母的 \(01\) 序列 hash 一下,然後就可以 \(O(26)\) 判斷了。
時間複雜度 \(O(26n)\)。
程式碼
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int N=200010; const ull base1=131,base2=13331; ull ha[3][27][N],power[3][N],h[5][27]; int n,m; char ch; int main() { scanf("%d%d",&n,&m); power[1][0]=power[2][0]=1; for (int i=1;i<=n;i++) { while (ch=getchar()) if (ch>='a' && ch<='z') break; for (int j=1;j<=26;j++) { ha[1][j][i]=ha[1][j][i-1]*base1+(j==ch-'a'+1); ha[2][j][i]=ha[2][j][i-1]*base2+(j==ch-'a'+1); } power[1][i]=power[1][i-1]*base1; power[2][i]=power[2][i-1]*base2; } while (m--) { int x,y,z; scanf("%d%d%d",&x,&y,&z); for (int i=1;i<=26;i++) { h[1][i]=ha[1][i][x+z-1]-ha[1][i][x-1]*power[1][z]; h[2][i]=ha[1][i][y+z-1]-ha[1][i][y-1]*power[1][z]; h[3][i]=ha[2][i][x+z-1]-ha[2][i][x-1]*power[2][z]; h[4][i]=ha[2][i][y+z-1]-ha[2][i][y-1]*power[2][z]; } sort(h[1]+1,h[1]+27); sort(h[2]+1,h[2]+27); sort(h[3]+1,h[3]+27); sort(h[4]+1,h[4]+27); bool flag=1; for (int i=1;i<=26;i++) if (h[1][i]!=h[2][i] || h[3][i]!=h[4][i]) flag=0; if (flag==1) printf("YES\n"); else printf("NO\n"); } return 0; }