luogu 1026 统计单词个数
此题 字符串匹配+dp
确实我的kmp,哈希需要练一练了,忘干净可咋办
补救用下string,十分方便
e.g:
1.询问a[i]是否是x子串,可以截取并判断前缀
x为截取串 x.find(a[i])==0判断前缀即可
2.s+='0',其后利用+=便可挪移下标
dp方程 f[i][j]表示串到i位分了j个块的最大单词数
需要枚举l更新答案,并非直接用i更新
dp[i][j]=max(dp[i][j],dp[l][j-1]+sum[l+1][j])
sum[i][j]代表串由i位到j位的子串匹配的单词数,需要预处理
#include<bits/stdc++.h> using namespace std; int p,k,n,m; string s,ch,a[10]; int f[205][50],sum[205][205]; //查询以i为起点,j为重点的串是否包含a[i],判断前缀 bool check(int i,int j){ string x=s.substr(i,j-i+1); for(int i=1;i<=n;i++) if(x.find(a[i])==0) return 1; return 0; } void init(){ s+='0';//补0挪移下标 cin>>p>>k; for(int i=1;i<=p;i++) cin>>ch,s+=ch; m=s.length()-1; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; //sum[i][j] 代表 由i到j 匹配的单词数 for(int i=m;i>=1;i--) for(int j=i;j>=1;j--){ sum[j][i]=sum[j+1][i]; if(check(j,i)) sum[j][i]++; } f[0][0]=0; for(int i=1;i<=k;i++) f[i][i]=f[i-1][i-1]+sum[i][i]; for(int i=1;i<=m;i++) f[i][1]=sum[1][i]; } int main(){ ios::sync_with_stdio(false); init(); for(int i=1;i<=m;i++) for(int j=1;j<=k&&j<i;j++) for(int l=j;l<i;l++) f[i][j]=max(f[i][j],f[l][j-1]+sum[l+1][i]); cout<<f[m][k]<<"\n"; return 0; }