ABC 331 F - Palindrome Query(字符串哈希,樹狀數組)

字符串哈希

[OI-Wiki](字符串哈希 - OI Wiki (oi-wiki.org))

分爲兩種哈希方式:以左爲高位以右爲高位

如果只是快速查詢每個字串的哈希值,用以左爲高位比較簡單,即

\[Hash[l...r]=Hash[1...r]-Hash[1...(l-1)]\times base^{r-l+1} \]

但是如果有修改操作,需要將每一位的 Hash 值存到數據結構裏(例如線段樹、樹狀數組),那麼採取以右爲高位可以直接通過區間求和來獲取 1...x 的Hash值。但是要注意求 [l,r] 的Hash值時需要再除以\(base^{l-1}\)

判斷迴文

將字符串正着哈希一遍,逆着哈希一遍,若兩個Hash值相等,則迴文。

具體實現可以開兩個樹狀數組。

代碼

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<ctime>
#include<stack>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!(c>='0'&&c<='9')) {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxn=1000005;
const long long mod=998244353;
int n,q;
char s[maxn];
long long d[maxn],d2[maxn],mi[maxn];
inline int lowbit(int x){
	return x&(-x);
}
void add(int x,long long v){
	for(int i=x;i<=n;i+=lowbit(i)) d[i]=(d[i]+v)%mod;
}
void add2(int x,long long v){
	for(int i=x;i<=n;i+=lowbit(i)) d2[i]=(d2[i]+v)%mod;
}
long long query(int x){
	long long res=0;
	for(int i=x;i>=1;i-=lowbit(i)) res+=d[i];
	return res%mod;
}
long long query2(int x){
	long long res=0;
	for(int i=x;i>=1;i-=lowbit(i)) res+=d2[i];
	return res%mod;
}
long long has(int l,int r){
	return (query(r)-query(l-1)+mod)%mod*mi[n-l]%mod;
}
long long has2(int l,int r){
	return (query2(r)-query2(l-1)+mod)%mod*mi[n-l]%mod;
}
int main()
{
	n=read(),q=read();
	mi[0]=1;
	for(int i=1;i<=n;i++){
		mi[i]=mi[i-1]*27%mod;
	}
	for(int i=1;i<=n;i++){
		s[i]=getchar();
		while(s[i]<'a'||s[i]>'z') s[i]=getchar();
		add(i,mi[i-1]*(s[i]-'a'+1)%mod);
		add2(n-i+1,mi[n-i]*(s[i]-'a'+1)%mod);
	}
	while(q--){
		int tp=read();
		if(tp==1){
			int x=read();
			char c=getchar();
			add(x,mi[x-1]*(c-s[x]+mod)%mod);
			add2(n-x+1,mi[n-x]*(c-s[x]+mod)%mod);
			s[x]=c;
		}else{
			int x=read(),y=read();
			if(has(x,y)==has2(n-y+1,n-x+1)) puts("Yes");
			else puts("No");
		}
	}
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章