【题解】String Bags 题解
\mathtt{Pre\ Explanation}
口胡出奇迹!STL 出奇迹!
本题解中
\mathtt{Solution}
作为一位合格的 OIer,你第一眼看到本题的想法是:暴力或者贪心。暴力在 Atcoder 赛制中显然不可取,于是你考虑贪心。
你在想:贪心的策略应该是每组选择最长的那个?可是不行啊,万一你选了最长的,后面接不上了怎么办?很有可能选个短的,后面再选个短的就可以接上?
既然贪心不行,那么你就开始思考 DP。你参考 LIS 的定义方法,决定定义
有了状态定义,你开始考虑转移。对于第
当然,你知道这个转移只有在
现在你苦于怎么判断后缀,这个时候你突然想起了 substr,你只需要通过它取出最后
你开始敲代码,敲的时候发现如果
最后,你成功地通过了此题。
\mathtt{Code}
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
//#define endl '\n'
#define IL inline
using namespace std;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
IL int read()
{
int x = 0,f = 1;
char c = getchar();
while(c <'0'|| c >'9'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
return x * f;
}
void write(int x)
{
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int n, f[105][105], c[105];
string t, s[105][105];
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
cin >> t;
cin >> n;
int m = t.size();
for(int i = 1;i <= n;i++)
{
cin >> c[i];
for(int j = 1;j <= c[i];j++)
{
cin >> s[i][j];
}
}
memset(f, 0x7f, sizeof(f));
f[0][0] = 0;
for(int i = 1;i <= n;i++)
{
memcpy(f[i], f[i - 1], sizeof(f[i - 1]));
for(int j = 1;j <= m;j++)
{
for(int k = 1;k <= c[i];k++)
{
int gft = s[i][k].size();
if(gft > j) continue;
if(t.substr(0, j).substr(j - gft) == s[i][k]) f[i][j] = min(f[i][j], f[i - 1][j - gft] + 1);
}
}
}
cout << (f[n][m] == 0x7f7f7f7f ? -1 : f[n][m]) << endl;
return 0;
}