luogu1026_統計單詞個數_區間dp
阿新 • • 發佈:2018-11-08
題意
https://www.luogu.org/problemnew/show/P1026
solution
- 設f[i][j]表示1~i分成j分,最多的單詞數
- 預處理一個sum[i][j]陣列,表示i~j包含的單詞數
- 預處理的時候需要注意一個順序j從大到小列舉,i從j到1列舉
- 那麼sum[i][j]=sum[i+1][j],再看看從i開始有沒有新的單詞,有就++
- dp的時候就是區間dp,dp[i][j]表示考慮到第i個字母,分為j段的最大字母數量
- 轉移就是列舉在哪裡分段dp[i][j]=dp[l][j-1]+sum[l+1][i]
code
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<cmath> #include<cstdlib> #include<ctime> using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; inline int read(){ char ch=' ';int f=1;int x=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } string s; string a[10]; int sum[210][210]; int f[210][210]; int q; bool check(int l,int r) { string x=s.substr(l,r-l+1); for(int i=1;i<=q;i++) { if(x.find(a[i])==0) return true; } return false; } int main() { int n,m;int i,j,k; s+='0'; n=read();m=read(); for(i=1;i<=n;i++) { string tmp; cin>>tmp; s+=tmp; } int len=s.length()-1; q=read(); for(i=1;i<=q;i++) cin>>a[i]; for(j=len;j>=1;j--) { for(i=j;i>=1;i--) { sum[i][j]=sum[i+1][j]; if(check(i,j)) sum[i][j]++; } } f[0][0]=0; for(i=1;i<=m;i++) { f[i][i]=f[i-1][i-1]+sum[i][i]; } for(i=1;i<=len;i++) { f[i][1]=sum[1][i]; } for(i=1;i<=len;i++) { for(j=1;j<=m&&j<i;j++) { for(k=j;k<i;k++) { f[i][j]=max(f[i][j],f[k][j-1]+sum[k+1][i]); } } } cout<<f[len][m]<<endl; return 0; }