CF727E Games on a CD(哈希)

常规做法,看出是破环成链后用哈希维护,只要枚举前k位,之后往后跳n次,看看是不是都有满足条件的字符串

注意,每个字符串只能用一次,因此还需要额外维护一个map表示是否已经使用

cf的数据比较强,卡了单哈希也卡了加法双哈希,因此用pll维护哈希即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int N=4e6+10;
const ll mod1=1e9+7;
const ll mod2=998244353;
ll base=131;
int n,k,g;
int len;
string s;
ll p1[N],p2[N];
ll h1[N],h2[N];
void init(){
    int i,j;
    p1[0]=p2[0]=1;
    for(i=1;i<=len;i++){
        p1[i]=p1[i-1]*base%mod1;
        p2[i]=p2[i-1]*base%mod2;
    }
    for(i=1;i<=len;i++){
        h1[i]=(h1[i-1]*base%mod1+(s[i]-'a'))%mod1;
        h2[i]=(h2[i-1]*base%mod2+(s[i]-'a'))%mod2;
    }
}
string t[N];
map<pll,ll> m1;
ll g1[N],g2[N];
int ans[N];
map<pll,ll> m2;
pll get(int l,int r){
    ll tmp1=(h1[r]-(h1[l-1]*p1[r-l+1]%mod1)+mod1)%mod1;
    ll tmp2=(h2[r]-(h2[l-1]*p2[r-l+1]%mod2)+mod2)%mod2;
    return {tmp1,tmp2};
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    cin>>s;
    s=s+s;
    s=" "+s;
    len=(n*k)<<1;
    cin>>g;
    int i,j;
    init();
    for(i=1;i<=g;i++){
        cin>>t[i];
        t[i]=" "+t[i];
        for(j=1;j<=k;j++){
            g1[i]=(g1[i]*base+(t[i][j]-'a'))%mod1;
            g2[i]=(g2[i]*base+(t[i][j]-'a'))%mod2;
        }
        m1[{g1[i],g2[i]}]=i;
    }
    int flag;
    for(i=1;i<=k;i++){
        m2.clear();
        flag=0;
        for(j=0;j<n;j++){
            pll tmp1=get(i+j*k,i+j*k+k-1);
            if(m2[tmp1]||!m1[tmp1]){
                flag=1;
                break;
            }
            m2[tmp1]=1;
            ans[j+1]=m1[tmp1];
        }
        if(!flag){
            cout<<"YES"<<endl;
            for(j=1;j<=n;j++){
                cout<<ans[j]<<" ";
            }
            cout<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
}
View Code

 

posted @ 2020-10-30 18:12  朝暮不思  阅读(116)  评论(0)    收藏  举报