Isomorphic Strings【字符串hash】-2020杭电多校8

题意

给一个字符串 (s) ,长度为 (n) ,问是否存在一个 (k) ,满足 (k∣n) ,将 (s) 分成相等的 (k) 段子串,每一段子串互为循环同构。其中,(1≤T≤1000,1≤n≤5⋅10^6, sum{n}leq2⋅10^7)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6863

分析

枚举 (n) 的所有满足条件的因子,然后对于每一个长度 (d),求出 ([1,d]) 的所有循环同构的字符串的 ( ext{Hash}) 值,进行标记,然后再遍历原字符串,求出划分后的其它所有子串是否满足循环同构。

已知 ( ext{Hash[i]})( ext{Hash[j]}) ,其中 (i<j),求 ([i+1,j]) 子串的 ( ext{Hash}) 值:

[ ext{ans}=( ext{Hash[j]}- ext{Hash[i]}· ext{base}^{j-i} \% mod+mod)\% mod ]

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int mod=12582917;
const int N=5e6+6;
const int maxn=2e7;
const int base=1543;
char ss[N];
int Hash[N],por[N];
int id[maxn],cnt;
void init()
{
    por[0]=1;
    for(int i=1;i<N;i++)
        por[i]=1LL*por[i-1]*base%mod;
}
void get_hash(int len)
{
    for(int i=1;i<=len;i++)
        Hash[i]=(1LL*Hash[i-1]*base%mod+ss[i])%mod;
}
bool solve(int d,int len)
{
    ++cnt;
    int tmp=Hash[d];
    id[tmp]=cnt;
    for(int i=1;i<=d;i++)//同构的其它串的hash值
    {
        tmp=(tmp-1LL*ss[i]*por[d-1]%mod+mod)%mod;
        tmp=(1LL*tmp*base+ss[i])%mod;
        id[tmp]=cnt;
    }
    for(int i=d+d;i<=len;i+=d)
    {
        int x=(Hash[i]-1LL*Hash[i-d]*por[d]%mod+mod)%mod;
        if(id[x]!=cnt) return false;
    }
    return true;
}
int main()
{
    int T,n;
    init();
    scanf("%d",&T);
    cnt=0;
    while(T--)
    {
        scanf("%d",&n);
        scanf("%s",ss+1);
        get_hash(n);
        bool f=0;
        for(int i=2;i*i<=n;i++)//每一段的长度
        {
            if(n%i) continue;
            int t=n/i;
            f=solve(i,n);
            if(f) break;
            if(i!=t) f=solve(t,n);
            if(f) break;
        }
        if(f==0&&n>1) f=solve(1,n);
        if(f) printf("Yes
");
        else printf("No
");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/1024-xzx/p/13501110.html