先区间DP处理区间单词个数,在线性DP一次求出答案,注意词典里可能有重复单词
#include<iostream> #include<cstdio> #define ri register int #define u unsigned long long namespace opt { inline u in() { u x(0),f(1); char s(getchar()); while(s<'0'||s>'9') { if(s=='-') f=-1; s=getchar(); } while(s>='0'&&s<='9') { x=(x<<1)+(x<<3)+s-'0'; s=getchar(); } return x*f; } } using opt::in; #define NN 205 #include<cstring> #include<algorithm> namespace mainstay { u N,K,M,pow[NN]={(u)1},sum[NN]; char s[NN]; int f[NN][NN],g[NN][NN]; const u bas=131; struct node{ u len,hash; }a[NN]; inline bool cmp(const node &x,const node &y){ return x.hash<y.hash; } inline void solve() { N=in()*20,K=in(); for(ri i(1);i<=N;++i) pow[i]=pow[i-1]*bas; for(ri i(1);i<=N;++i){ char _s(getchar()); while(_s<'a'||_s>'z') _s=getchar(); sum[i]=sum[i-1]*bas+_s-'a'+1; } M=in(); for(ri i(1);i<=M;++i){ scanf("%s",s+1); a[i].len=std::strlen(s+1); for(ri j(1);j<=a[i].len;++j) a[i].hash=a[i].hash*bas+s[j]-'a'+1; } std::sort(a+1,a+M+1,cmp); for(ri len(1);len<=N;++len){ for(ri i(1),j(i+len-1);j<=N;++i,++j){ g[i][j]=g[i+1][j]; u pre(0); for(ri k(1);k<=M;++k){ if(pre==a[k].hash) continue; if(a[k].len<=len&&a[k].hash==sum[i+a[k].len-1]-pow[a[k].len]*sum[i-1]) ++g[i][j]; pre=a[k].hash; } } } std::memset(f,-0x3f,sizeof(f)); f[0][0]=0; for(ri i(1);i<=N;++i){ for(ri j(1);j<=K;++j){ for(ri k(0);k<=i-1;++k){ f[i][j]=std::max(f[i][j],f[k][j-1]+g[k+1][i]); } } } std::cout<<f[N][K]; } } int main() { //freopen("x.txt","r",stdin); mainstay::solve(); }