• hdu 6863 Isomorphic Strings 哈希+求公因子


    题意:

    t组输入,每组数据输入一个整数n,代表字符串长度。下面再输入一个字符串

    你需要判断这个字符串能不能分成大于1段,且这些段的最小表示法是一样的

    例如:abccab,它可以分成2段,分别是abc和cab,它们都使用最小表示法(也就是字典序最小表示)表示之后都是abc,所以这两个串一样

    题解:

    因为你需要把字符串分成若干段,假设分成x段,那么x肯定满足n%x==0

    这里就有两种方法,第一种就是枚举n的因子,然后再暴力去判断这个因子可不可以

    另一种就是:假如存在一个可以满足题意的因子x(也就是说一段的长度为x,且每一段都相等),那么分成n/x段,每一段里面每一个字母的个数肯定要保持一样多

    那么我们可以去找所有字母个数的最大公因子,设为ans,然后在1-ans里面暴力枚举就行。这样比去暴力枚举n的因子复杂度小

    我们如何判断一个因子x可以不可满足题意?

    对于一个串abccab,我们可以得出来a、b、c字母得个数都是2,那么它们和n的最大公因数就是2

    那么长度为n的串,最多分成2段,每一段的长度n/2

    然后我们开始暴力枚举[1,2)这个区间的因子,首先要判断一下n%x==0,不等于0这个因子就不行

    这个枚举的是将几个n/2合并,例如1是满足n%x==0

    这个时候abc为一段,cab为一段(如果x==2,那么就是将2个n/2合并成一段,即abccab为一段,因为题目要求必须将字符串分开,所以2不可以)

    对于第一段abc,我们先标记一下abc的哈希值,然后再标记一下bca的哈希值,再标记cab的哈希值

    然后再去判断后面的段的哈希值是否被标记过,如果标记过就没事,没标记过就证明这个因子不行

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<map>
    using namespace std;
    typedef unsigned long long ull;
    typedef long long ll;
    const int blo=13331;
    const int maxn = 5e6+5;
    ll xp[maxn],hash_1[maxn],num[maxn];
    map<ll,ll>r;
    void init()
    {
        xp[0]=1;
        for(ll i=1; i<maxn; i++)
            xp[i]=xp[i-1]*blo;
    }
    ll make_hash(char str[],ll hash_[],ll len)
    {
        hash_[0]=0;
        for(ll i=1; i<=len; i++)
        {
            hash_[i]=hash_[i-1]*blo+(str[i]-'a'+1);
            //cout<<hash_[i]<<" ";
        }
        return len;
    }
    char str[maxn];
    int main()
    {
    
        init();
        ll t;
        scanf("%lld",&t);
        while(t--)
        {
            //r.clear();
            ll n,flag=1;
            scanf("%lld",&n);
            scanf("%s",str+1);
            make_hash(str,hash_1,n);
            memset(num,0,sizeof(num));
            for(ll i=1;i<=n;++i)
            {
                num[str[i]-96]++;
            }
            ll ans=n;
            for(ll i=1;i<=26;++i)  //如果分组之后每组字符串最小表示法都一样,那么里面的每个字母的数量也一样,所以我们可以
            {           //以此来下手
                if(num[i])
                ans=__gcd(ans,num[i]);  //这个ans里面放的就是最多你能分成多少组
            }
            ll u=n/ans;  //按照最大分成ans组,每一组的长度
            if(u==1 && n!=1)
            {
                flag=0;
            }
            else
            {
                for(ll k=1;k<ans;++k)  //枚举判断
                {
                    ll len=k*u;
                    if(n%len)
                    {
                        continue;
                    }
                    r.clear();
                    flag=0;
                    ll temp=hash_1[len]-hash_1[0]*xp[len];
                    r[temp]=1;
                    for(ll i=1;i<=len;++i)  //将一个字符串的各种类型字符串哈希值都算出来,并标记
                    { //例如字符串abc,你不仅要算出来abc的哈希值,还要算出来bca、cab的哈希值
                        temp=temp*blo+(str[i]-96);
                        r[temp-hash_1[i]*xp[len]]=1;
                    }
                    for(ll j = 1; j * len <= n; j++)  //判断后面几组是否和第一组一样
                    {
    
                        if(r[hash_1[j*len]-hash_1[(j - 1)*len]*xp[len]]==0)
                        {
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 0)
                    {
    
                        break;
                    }
                }
            }
            if(!flag)
                printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    Python的未来发展方向
    loadrunner分析之网页、网络、资源分析
    Django框架Day2之Template
    Django框架Day3之Models
    Appium 常用的API函数
    Django框架Day1之url和views
    Loadrunner常用分析点
    WEB性能测试用例设计
    python之高阶函数map()和reduce()
    python csv文件打开错误:_csv.Error: line contains NULL byte
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13508782.html
Copyright © 2020-2023  润新知