arc099F - Eating Symbols Hard
题目大意
题解
哈希,表示成Σai*p^i(i可以为负),设Si表示后缀哈希值,sumi表示前缀>+1<-1的和
那么区间[l,r]满足当且仅当\(S_l-S_r*p^{sum_r-sum_{l-1}}=S_1\),移项后乘上p^sum(l-1),枚举lmap统计
要写双哈希
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 1000000007
#define Mod 1000000005
#define ll long long
//#define file
using namespace std;
ll p[250001],P[250001],pp[250001],PP[250001],hs[250001],Hs[250001],s,S,p1,p2,p3,p4,ans;
int sum[250001],n,i,j,k,l;
char st[250001];
map<pair<int,int>,int> mp;
map<pair<int,int>,int> :: iterator I;
ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
ll Pow(int t) {return (t>=0)?p[t]:P[-t];}
ll Pow2(int t) {return (t>=0)?pp[t]:PP[-t];}
int main()
{
#ifdef file
freopen("arc099f.in","r",stdin);
#endif
scanf("%d",&n);
scanf("%s",st+1);
p1=123456789,p2=qpower(p1,Mod);
p3=114514191,p4=qpower(p3,Mod);
p[0]=P[0]=pp[0]=PP[0]=1;
fo(i,1,n) p[i]=p[i-1]*p1%mod,P[i]=P[i-1]*p2%mod,pp[i]=pp[i-1]*p3%mod,PP[i]=PP[i-1]*p4%mod;
fd(i,n,1)
{
switch (st[i])
{
case '>':{sum[i]=1,s=s*p1%mod;break;}
case '<':{sum[i]=-1,s=s*p2%mod;break;}
case '+':{s=(s+1)%mod;break;}
case '-':{s=(s-1)%mod;break;}
}
s=(s+mod)%mod;
hs[i]=s;
}
s=0;
fd(i,n,1)
{
switch (st[i])
{
case '>':{sum[i]=1,s=s*p3%mod;break;}
case '<':{sum[i]=-1,s=s*p4%mod;break;}
case '+':{s=(s+1)%mod;break;}
case '-':{s=(s-1)%mod;break;}
}
s=(s+mod)%mod;
Hs[i]=s;
}
fo(i,1,n) sum[i]+=sum[i-1];
mp[pair<int,int>(0,0)]=1;
fd(i,n,1)
{
s=((hs[i]-hs[1])*Pow(sum[i-1])%mod+mod)%mod;
S=((Hs[i]-Hs[1])*Pow2(sum[i-1])%mod+mod)%mod;
I=mp.find(pair<int,int>(s,S));
if (I!=mp.end())
ans+=I->second;
++mp[pair<int,int>(hs[i]*Pow(sum[i-1])%mod,Hs[i]*Pow2(sum[i-1])%mod)];
}
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}