思路:
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;
}