CodeForces 536B Tavas and Malekas :构造长为n的串,使m个串的开头是给定的某个字符串,求构造方案数 kmp/hash
本题的难点在于--->看懂题意
因为比赛纠结于A的二分,比赛还没结束就暴走睡觉了TUT今天起来看了看B===卧槽题意和A一样恶心啊有木有==
回到本题,看明白之后首先映入眼前的就是--->暴力大法好
这样必然是可以hack超时的,必须要对串进行处理哪些后缀和前缀相等
最常规的莫过于kmp里面的next,从结尾一直next找找找到找不到,那些地方表示和后缀相同,这个和之前做过的hdu某题类似
这是用kmp写的本题代码
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 #define LL long long 6 #define MOD 1000000007 7 LL vis[1000005],f[1000005],Next[1000005]; 8 char s[1000005]; 9 void getnext(char *B,LL m){ 10 LL i,j; 11 Next[1]=j=0; 12 for (i=2;i<=m;i++){ 13 while (j>0&&B[j+1]!=B[i]) j=Next[j]; 14 if (B[j+1]==B[i]) j++; 15 Next[i]=j; 16 } 17 i=m; 18 while (Next[i]){ 19 i=Next[i]; 20 f[i]=1; 21 } 22 } 23 int main() 24 { 25 LL n,m,len,ans,pre,cnt,i,x,tmp; 26 scanf("%I64d%I64d",&n,&m); 27 scanf("%s",s+1); 28 len=strlen(s+1); 29 memset(vis,0,sizeof(vis)); 30 memset(f,0,sizeof(f)); 31 for (i=1;i<=m;i++){ 32 scanf("%I64d",&x); 33 vis[x]=1; 34 } 35 getnext(s,len); 36 // for (i=1;i<=len;i++) printf("%I64d",f[i]); printf("\n"); 37 cnt=pre=0; 38 for (i=1;i<=n;i++){ 39 if (vis[i]){ 40 if (pre&&pre+len>i){ 41 tmp=len-(i-pre); 42 if (f[tmp]!=1){ 43 printf("0\n"); 44 return 0; 45 } 46 } 47 pre=i; 48 } 49 if (pre==0||pre+len<=i) cnt++; 50 } 51 ans=1; 52 for (i=1;i<=cnt;i++) ans=ans*26%MOD; 53 printf("%I64d\n",ans); 54 return 0; 55 }
当然,判断两个字符串的另外一种方法hash黑科技也可以,听说单hash容易被卡,交了几发都过了,上一个双hash的==
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 #define LL long long 6 #define MOD 1000000007 7 struct Hash{ 8 LL B,mod,len,Has[1000005],Base[1000005]; 9 void init(char *s,LL _len,LL _B,LL _mod){ 10 B=_B; mod=_mod; len=_len; 11 Base[0]=1; Has[0]=0; 12 for (LL i=1;i<=len;i++){ 13 Base[i]=Base[i-1]*B%mod; 14 Has[i]=(Has[i-1]*B+s[i-1]-'a'+1)%mod; 15 } 16 return; 17 } 18 LL gethash(LL l,LL r){ 19 return ((Has[r]-Has[l-1]*Base[r-l+1])%mod+mod)%mod; 20 } 21 }; 22 LL vis[1000005]; 23 char s[1000005]; 24 Hash H1,H2; 25 int main() 26 { 27 LL n,m,len,ans,pre,cnt,i,x,tmp; 28 scanf("%I64d%I64d",&n,&m); 29 scanf("%s",s); 30 len=strlen(s); 31 H1.init(s,len,171,MOD); 32 H2.init(s,len,191,MOD+2); 33 memset(vis,0,sizeof(vis)); 34 for (i=1;i<=m;i++){ 35 scanf("%I64d",&x); 36 vis[x]=1; 37 } 38 cnt=pre=0; 39 for (i=1;i<=n;i++){ 40 if (vis[i]){ 41 if (pre&&pre+len>i){ 42 tmp=len-(i-pre); 43 if (H1.gethash(1,tmp)!=H1.gethash(len-tmp+1,len) 44 ||H2.gethash(1,tmp)!=H2.gethash(len-tmp+1,len)){ 45 printf("0\n"); 46 return 0; 47 } 48 } 49 pre=i; 50 } 51 if (pre==0||pre+len<=i) cnt++; 52 } 53 ans=1; 54 for (i=1;i<=cnt;i++) ans=ans*26%MOD; 55 printf("%I64d\n",ans); 56 return 0; 57 }