Hdu多校8-1009 hdu-6863 Isomorphic Strings

题目链接:点击跳转

Problem Description
在这里插入图片描述
Input
在这里插入图片描述

Output
For each test case, output one line containing ‘‘Yes’’ or ‘‘No’’ (without quotes).

Sample Input

6
1
a
2
aa
3
aab
4
abba
6
abcbcc
8
aaaaaaaa

Sample Output

No
Yes
No
Yes
No
Yes

题目大意:求给出的字符串的长度的因子(大于1的),以该因子拆分原串,是否每一串都可以是其他串的循环同构
解题思路:这里用string的substr和find函数来解决的,当然,string的封装方法的效率都相当低,所以需要维护一个前缀和(O(n*26))来优化,因为如果是循环同构,那么每个字符的数量一定是相等的,如果都相等,才需要去比较。找到一个k满足题意就可以退出输出Yes,没有找到则输出No。

代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
inline void FAST_IO() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
int n;
string s;
int fac[50005],tot,sum[26][5000005];
inline void getFac(){
    tot=0;
    for(int i=2;i*i<=n;i++){
        if(n%i==0)fac[tot++]=i;
        if(i*i!=n)fac[tot++]=n/i;
    }
    fac[tot++]=n;
}
signed main(){
    FAST_IO();
    int Case;
    cin>>Case;
    while(Case--){
        cin>>n>>s;
        if(n==1){
            cout<<"No"<<endl;
            continue;
        }
        for(int i=0;i<26;i++)sum[i][0]=0;
        sum[s[0]-'a'][0]=1;
        for(int i=1;i<n;i++){
            for(int j=0;j<26;j++){
                sum[j][i]=sum[j][i-1];
            }
            sum[s[i]-'a'][i]++;
        }
        getFac();
        bool f=false;
        for(int i=0;i<tot;i++){
            f=true;
            int k=n/fac[i];
            for(int j=k;j<n;j+=k){
                if(!f)break;
                for(int l=0;l<26;l++){
                    if(sum[l][j+k-1]-sum[l][j-1]!=sum[l][k-1]){
                        f=false;
                        break;
                    }
                }
            }
            if(!f)continue;
            string str=s.substr(0,k);
            str+=str;
            for(int j=k;j<n;j+=k){
                string str1=s.substr(j,k);
                if(str.find(str1)==-1){
                    f=false;
                    break;
                }
            }
            if(f)break;
        }
        if(f){
            cout<<"Yes"<<endl;
        }else{
            cout<<"No"<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值