BJ simulates similar substrings [hash + union search]

Topic description:

write picture description here

Problem solving ideas:

Hash the 26 letters separately, and each bit uses only 0 and 1 to indicate whether this bit is the letter i.
When asking, the 26 letters are also compared separately, and the hashes in the equivalence class are added up.
The difference is at most 1, that is, the final hash value will only have a shape like b a s e i The difference can be judged.

#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();c!='-'&&(c<'0'||c>'9');c=getchar());
    if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=100005,C=26;
const ll base=123LL,invbase=3449391168254631603LL;
int n,m,id[N];
int tot,first[N],nxt[N<<1],to[N<<1],c[N<<1];
int dep[N],fa[N][20];
ll bin[N],binv[N],g[N][26],f[N][26],sum1[C],sum2[C];
map<ll,bool>mp;
int find(int x){return id[x]==x?x:id[x]=find(id[x]);}
void merge(int x,int y){id[find(y)]=find(x);}
void add(int x,int y,int z)
{
    nxt[++tot]=first[x],first[x]=tot,to[tot]=y,c[tot]=z;
}
void dfs(int u)
{
    for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int e=first[u];e;e=nxt[e])
    {
        int v=to[e];
        if(v==fa[u][0])continue;
        fa[v][0]=u,dep[v]=dep[u]+1;
        for(int i=0;i<C;i++)
        {
            g[v][i]=g[u][i]+bin[dep[v]]*(c[e]==i);
            f[v][i]=f[u][i]*base+(c[e]==i);
        }
        dfs(v);
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int det=dep[x]-dep[y];
    for(int i=0;i<20;i++)if(det>>i&1)x=fa[x][i];
    for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return x==y?x:fa[x][0];
}
ll gethash(int u,int v,int t,int i)
{
    ll s1=(g[u][i]-g[t][i])*binv[dep[t]];
    ll s2=f[v][i]-f[t][i]*bin[dep[v]-dep[t]];
    return s1*bin[dep[v]-dep[t]]+s2;
}
bool check(int u1,int v1,int u2,int v2)
{
    int t1=lca(u1,v1),t2=lca(u2,v2);
    if(dep[u1]+dep[v1]-2*dep[t1]!=dep[u2]+dep[v2]-2*dep[t2])return false;
    for(int i=0;i<C;i++)sum1[i]=sum2[i]=0;
    for(int i=0;i<C;i++)
    {
        sum1[id[i]]+=gethash(u1,v1,t1,i);
        sum2[id[i]]+=gethash(u2,v2,t2,i);
    }
    int cnt=0;
    for(int i=0;i<C;i++)if(id[i]==i)
    {
        if(sum1[i]==sum2[i])continue;
        if(!mp.count(sum1[i]-sum2[i]))return false;
        cnt++;
    }
    return cnt<=2;
}
int main()
{
    //freopen("lx.in","r",stdin);
    int x,y,z;
    n=getint();
    bin[0]=binv[0]=1,mp[1]=mp[-1]=1;
    for(int i=1;i<=n;i++)
    {
        bin[i]=bin[i-1]*base,binv[i]=binv[i-1]*invbase;
        mp[bin[i]]=mp[-bin[i]]=1;
    }
    for(int i=1;i<n;i++)
    {
        x=getint(),y=getint(),z=getchar()-'a';
        add(x,y,z),add(y,x,z);
    }
    dfs(1);
    m=getint();int k,u1,v1,u2,v2;char ch[2];
    while(m--)
    {
        k=getint(),u1=getint(),v1=getint(),u2=getint(),v2=getint();
        for(int i=0;i<C;i++)id[i]=i;
        while(k--)scanf("%s",ch),merge(ch[0]-'a',ch[1]-'a');
        for(int i=0;i<C;i++)find(i);
        check(u1,v1,u2,v2)?puts("YES"):puts("NO");
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324607898&siteId=291194637