常规做法,看出是破环成链后用哈希维护,只要枚举前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; }