D - String Bags Editorial by en_translator
To come straight to the point, this problem can be solved with dynamic programming (DP).
Let \(dp[\) how many bags were processed? \(][\) how long is the prefix of \(T\) that matched? \(] = \) { minimum money required }.
Consider concatenating a string \(X\) in the \((i+1)\)-th bag to the end of \(S\). Then, transition from \(dp[i][|S|]\) to \(dp[i+1][|S|+|X|]\) is possible only if the \((|S|+1)\)-th through \((|S|+|X|)\)-th characters coincide with \(X\).
Under the constraint of this problem, we can naively check this condition.
Also, not choosing a string corresponds to the transition from \(dp[i][j]\) to \(dp[i+1][j]\).
By implementing this DP, the problem can be solved in about \(O(NM|S||T|)\) time (where \(M\) is the number of strings in a bag).
Sample code (C++):
#include<bits/stdc++.h>
using namespace std;
int dp[105][105];
int main(){
for(int i=0;i<105;i++){
for(int j=0;j<105;j++){
dp[i][j]=1e9;
}
}
dp[0][0]=0;
string t;
cin >> t;
int tl=t.size();
int n;
cin >> n;
for(int i=0;i<n;i++){
for(int j=0;j<105;j++){dp[i+1][j]=dp[i][j];}
int m;
cin >> m;
while(m>0){
m--;
string s;
cin >> s;
int sl=s.size();
for(int j=0;j+sl<=tl;j++){
bool ok=true;
for(int k=0;k<sl;k++){
if(t[j+k]!=s[k]){ok=false;break;}
}
if(ok){
dp[i+1][j+sl]=min(dp[i+1][j+sl],dp[i][j]+1);
}
}
}
}
if(dp[n][tl]>5e8){dp[n][tl]=-1;}
cout << dp[n][tl] << "\n";
return 0;
}
posted:
last update: