2026.10.05总结

认证学习乱搞字符串HASH

题单地址
主要是进制位hash,形成双hash+ull自然溢出的写法
base:233,911,131;
mod:1e9+7,1e7+9,13697891,998244353;
用正、反hash \(O(1)\) 比较,\(O(LEN)\)预处理。
区间hash:

  hash=hs[r]-hs[l-1]*sum[r-l+1];//sum预处理进制位

异或hash

inline ull clhs(string & ss){
    ull cnt=0;
    for(int i=1;i<=n;i++){
        cnt^=w[i][joi(ss[i])];
    }
    return cnt;
}
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
for(int i=1;i<=n;i++){
    for(int c=0;c<=2;c++){
        w[i][c]=rng();
        prw[i][c]=prw[i-1][c]^w[i][c];
    }
}

有意义的题

ODT+异或hash

#include <bits/stdc++.h>
using namespace std;
#define puu pair<unsigned long long,unsigned long long>
#define ull unsigned long long
#define ll long long
#define bs1 233
#define bs2 911
#define mod1 13697891
#define mod2 1e9+7
#define fi first
#define se second
const int N=2e5+10;
int n,tot;
string sa,sb,sc;
string s[20],t;
ull w[N][3],prw[N][3];
ull hs[15];
ull now;
map<int,pair<int,int>>odt;
map<ull,int>mp;
inline int joi(char c){
    if(c=='J')return 0;
    if(c=='O')return 1;
    return 2;
}
inline char ioj(int a){
    if(a==0)return 'J';
    if(a==1)return 'O';
    return 'I';
}
inline void cross(string s1,string s2,string & ss){
    ss.resize(n+2);
    int qwq,pwp;
    for(int i=1;i<=n;i++){
        qwq=joi(s1[i]);
        pwp=joi(s2[i]);
        qwq=(6-pwp-qwq)%3;
        ss[i]=ioj(qwq);
    }
    return ;
}
inline ull clhs(string & ss){
    ull cnt=0;
    for(int i=1;i<=n;i++){
        cnt^=w[i][joi(ss[i])];
    }
    return cnt;
}
inline auto split(int pos){
    auto it=odt.lower_bound(pos);
    if(it!=odt.end()&&it->fi==pos)return it;
    --it;
    int l=it->fi,r=it->se.fi,c=it->se.se;
    odt[l]={pos-1,c};
    return odt.insert({pos,{r,c}}).fi;
}
inline void assign(int l,int r,int c){
    auto itr=split(r+1),itl=split(l);
    int L,R,cc;
    for(auto it=itl;it!=itr;it++){
        L=it->fi,R=it->se.fi,cc=it->se.se;
        now^=prw[R][cc]^prw[L-1][cc];
    }
    odt.erase(itl,itr);
    auto it=odt.insert({l,{r,c}}).fi;
    now^=prw[r][c]^prw[l-1][c];
    auto nxt=next(it);
    if(nxt!=odt.end()&&nxt->se.se==c){
        it->se.fi=nxt->se.fi;
        odt.erase(nxt);
    }
    if(it!=odt.begin()){
        auto prv=prev(it);
        if(prv->se.se==c){
            prv->se.fi=it->se.fi;
            odt.erase(it);
        }
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;
    cin>>sa>>sb>>sc;
    s[1]=" "+sa;
    s[2]=" "+sb;
    s[3]=" "+sc;
    cross(s[1],s[2],s[4]);
    cross(s[2],s[3],s[5]);
    cross(s[3],s[1],s[6]);
    cross(s[4],s[5],s[7]);
    cross(s[5],s[6],s[8]);
    cross(s[6],s[4],s[9]);
    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
    for(int i=1;i<=n;i++){
        for(int c=0;c<=2;c++){
            w[i][c]=rng();
            prw[i][c]=prw[i-1][c]^w[i][c];
        }
    }
    for(int k=1;k<=9;k++){
        mp[clhs(s[k])]=1;
    }
    int q;
    cin>>q;
    cin>>t;
    t=' '+t;
    now=clhs(t);
    if(mp.count(now)){
        cout<<"Yes\n";
    }
    else cout<<"No\n";
    for(int i=1,st=1;i<=n+1;i++){
        if(i==n+1||t[i]!=t[st]){
            odt[st]={i-1,joi(t[st])};
            st=i;
        }
    }
    odt[n+1]={n+1,-1};
    int l,r;
    char c;
    for(int i=1;i<=q;i++){
        cin>>l>>r>>c;
        assign(l,r,joi(c));
        cout<<(mp.count(now)?"Yes":"No")<<'\n';
    }
    return 0;
}
posted @ 2026-10-05 19:34  xmd11  阅读(4)  评论(1)    收藏  举报