问题 C: 重铸神器(dp+哈希)

思路:

dp[j]:前j个字符串且当前第j个位置往前匹配第x个串的可行性
单纯找就是O(50*3e5),匹配的过程改成hash的优化近乎O1    

 赛中哈希值不同debug老久的问题:

哈希的初始值p[0]=1;下面num的递推过程的hash值的初始值是0不是1!!!!

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=3e5+100;
typedef int LL;
///const LL mod=998244353;
const LL base=131;
inline LL read(){LL x=0,f=1;char ch=getchar();  while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
char str[maxn];
char ptr[55][maxn];
LL length[55];
LL dp[maxn];
LL p[maxn];
LL strhashval[maxn];
LL ptrhashval[55];
///换哈希匹配
///重复使用--完全背包
LL cal(LL f[],LL l,LL r){
    return (f[r]-f[l-1]*p[r-l+1]);
}
bool check(char str[],LL l1,LL r1,LL id){
 
     if(  cal(strhashval,l1,r1) == ptrhashval[id]) return true;
     else return false;
 
}
int main(void)
{
  ///cin.tie(0);std::ios::sync_with_stdio(false);
  p[0]=1;
  for(LL i=1;i<maxn-10;i++) p[i]=p[i-1]*base;
 
 
  scanf("%s",str+1);
  LL len=strlen(str+1);
 
 
 
  for(LL i=1;i<=len;i++){
     strhashval[i]=(strhashval[i-1]*base+(str[i]-'a'+1));
  }
 
 
 
  LL n;n=read();
 
  for(LL i=1;i<=n;i++)  scanf("%s",(ptr[i]+1));
 
 
 
  for(LL i=1;i<=n;i++)  length[i]=strlen(ptr[i]+1);
 
  for(LL i=1;i<=n;i++){
 
 
     LL num=0;///初始为0不是1!!!!
 
            for(LL j=1;j<=length[i];j++){
 
                num=(num*base+(ptr[i][j]-'a'+1));
 
            }
            ptrhashval[i]=num;
 
  }
 
 
   dp[0]=1;
 
    ///dp[j]:前j个字符串且当前第j个位置往前匹配第x个串的可行性
    
  for(LL i=1;i<=len;i++){
 
     for(LL j=1;j<=n;j++){
 
            if(check( str,i-length[j]+1,i,j)==true) {  ///kmp优化或者哈希
  ///              cout<<"i= "<<i<<" "<<"id="<<j<<" "<<"\n";
                dp[i]|=dp[i-length[j]];
            }
 
 
 
     }
  }
 
  bool flag=1;
  ///for(LL i=1;i<=len;i++){
  ///  for(LL j=1;j<=n;j++){
  ///      cout<<dp[i]<<" ";
        if(dp[len]!=0){
            flag=0;
        }
 /// }
  if(flag==0){
    printf("yes\n");
  }
  else printf("no\n");
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/114833023
今日推荐