constint N = 110; int dp[N][N]; // dp[i][j] = 前 i 个袋子中匹配 T 的前缀长度为 j 时所需的最少钱数。 string t;
template <typename T>
inline T read(){ T sum = 0, fl = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') fl = -1; for (; isdigit(ch); ch = getchar()) sum = sum * 10 + ch - '0'; return sum * fl; }
template <typename T>
inlinevoidwrite(T x){ if (x < 0) putchar('-'), write<T>(-x); static T sta[35]; int top = 0; do { sta[top++] = x % 10, x /= 10; } while (x); while (top) putchar(sta[--top] + 48); }
intmain(){ IOS memset(dp, INF, sizeof(dp)); dp[0][0] = 0; cin >> t; int tl = t.size(), n; cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < 110; j++) dp[i + 1][j] = dp[i][j]; int m; cin >> m; while (m--) { string s; cin >> s; int sl = s.size(); // 比较 for (int j = 0; j + sl <= tl; j++) { bool flag = true; for (int k = 0; k < sl; k++) if (t[j + k] != s[k]) { flag = false; break; } if (flag) 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"; return0; }