首页 > 其他 > 详细

Codeforces727E-Games on a CD

时间:2020-03-15 17:48:51      阅读:59      评论:0      收藏:0      [点我收藏+]

Codeforces727E-Games on a CD

题意

给一个字符串\(s\)(从一个环上的某点切开得到),其长度为n*k(由n个长度为k的子串拼成),以及t个长度为k的字符串,问这t个字符串能否按一定顺序首尾相接,拼成原环(如果可以,依次打印出第i个使用的字符串的序号)

题解

因为原串是个环,所以先将字符串变成两倍。将给出的t个串Hash(双模数),将其存入map中。在原串中从1到k枚举起点i,如果能将它分成t个长度k的子串,且Hash值均在map中,并且没有在本次操作中已经使用过,那么就输出答案。

1、vis[i]表示序号为i的字符串在第几次被使用过
2、要用双哈希,一开始只用了一个模数被卡了

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+10;
const int base=131;
int mod[2]={1000000007,998244353};

int n,k,t,len;
char s[N],tmp[N];
ll Hash[N][2];
map<pair<ll,ll>,int> m;
int ans[N],vis[N];
ll sum[2];

//vis
//双哈希 

void init(){
    sum[0]=sum[1]=1;
    for(int i=1;i<=k;i++){
        sum[0]=(sum[0]*base)%mod[0];
        sum[1]=(sum[1]*base)%mod[1];
    } 
}

void getHash(){
    for(int i=1;i<=len;i++){
        Hash[i][0]=(Hash[i-1][0]*base%mod[0]+s[i])%mod[0]; 
        Hash[i][1]=(Hash[i-1][1]*base%mod[1]+s[i])%mod[1];
    }
}

bool solve(int st){
    int l=st,r=st+k-1;
    for(int i=1;i<=n;i++){
        ll now0=(Hash[r][0]-Hash[l-1][0]*sum[0]%mod[0]+mod[0])%mod[0];
        ll now1=(Hash[r][1]-Hash[l-1][1]*sum[1]%mod[1]+mod[1])%mod[1];
        pair<ll,ll> p=make_pair(now0,now1);
        if(!m.count(p)) return 0;
        if(vis[m[p]]==st) return 0;
        ans[i]=m[p];
        vis[ans[i]]=st;
        l+=k;r+=k;
    } 
    return 1;
}

int main(){
    scanf("%d%d",&n,&k);
    scanf("%s",s+1);
    len=n*k;
    for(int i=len+1;i<=2*len;i++) s[i]=s[i-len];
    s[2*len+1]='\0';
    len*=2;
    init();
    getHash();
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%s",tmp+1);
        ll hash0=0,hash1=0; 
        for(int j=1;j<=k;j++){
            hash0=(hash0*base%mod[0]+tmp[j])%mod[0];
            hash1=(hash1*base%mod[1]+tmp[j])%mod[1];
        }
        m[make_pair(hash0,hash1)]=i;
    }
    bool flag=0;
    for(int i=1;i<=k;i++){
        if(solve(i)){
            flag=1;
            break;
        }
    }
    if(flag){
        printf("YES\n");
        for(int i=1;i<=n;i++){
            if(i!=1) printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
    }else printf("NO\n");
    return 0;
} 

Codeforces727E-Games on a CD

原文:https://www.cnblogs.com/qjy73/p/12498585.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!