tokitsukaze and Similar String(字串雜湊)
阿新 • • 發佈:2018-12-10
題目連結:
tokitsukaze and Similar String
題意:
tokitsukaze獲得了一個長度為n (1≤n≤10^5),由a-z小寫字母組成的字串。
我們定義兩個字串是相似的,當且僅當能通過多次以下操作,使得兩個字串相等。並且把需要操作的最小次數,稱為兩個字串的相似度。
操作是這樣的:選擇一個字串,把字串的每個字母都替換為字母表上的下一個字母,同時,我們認為z的下一個字母為a,比如選擇"acdz",操作一次後變為"bdea"。
現在tokitsukaze從字串中任取兩個子串,她想知道它們是不是相似的,如果它們相似,請輸出相似度,如果它們不相似,請輸出-1。
思路:
字串雜湊。
預處理26種變化的Hash表,每次詢問用Hash表來判斷子串是否相等。若 x 的第 i 種變化與 y 相等,ans=min(i,26-i) 。
Code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; const int MAX = 1e5+10; const ll mod = 1e9+7; const ull P = 131; int n,q; char s[MAX]; ull Hash[MAX][30]; ull pw[MAX]; ull get(int l,int r,int t){ return Hash[r][t]-Hash[l-1][t]*pw[r-l+1]; } int main() { scanf("%d%s%d",&n,s+1,&q); pw[0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<26;j++){ Hash[i][j]=Hash[i-1][j]*P+(s[i]-'a'+1+j)%26; if((s[i]-'a'+1+j)%26==0) Hash[i][j]+=26; } pw[i]=pw[i-1]*P; } while(q--){ int x,y,len; scanf("%d%d%d",&x,&y,&len); int t = ((s[y]-'a'+1+26)-(s[x]-'a'+1))%26; if(get(x,x+len-1,t)==get(y,y+len-1,0)){ printf("%d\n",min(t,26-t)); } else{ printf("-1\n"); } } return 0; }