canuc80k2009·10/50

Ghép Chuỗi Từ Từ Điển

Nộp bài trên LQDOJ

Bài 20 · Trie

Đếm số cách nối một dãy từ trong từ điển để nhận đúng chuỗi đích, với thứ tự ký tự được giữ nguyên.

Một cách ghép là một dãy từ có phép nối đúng bằng . Một từ có thể được chọn lại; hai cách khác nhau khi dãy vị trí kết thúc các từ khác nhau.

Input

  • Dòng đầu chứa chuỗi đích .
  • Dòng thứ hai chứa số nguyên .
  • dòng tiếp theo chứa các từ trong từ điển, đôi một khác nhau.

Output

  • In số cách biểu diễn thành phép nối của một hoặc nhiều từ trong từ điển, lấy modulo .

Constraints

  • .
  • .
  • và các từ chỉ gồm chữ cái thường .
  • Các từ trong từ điển đôi một khác nhau.
  • Tổng độ dài của từ không vượt quá .
  • Mỗi từ trong từ điển có thể được dùng nhiều lần ở các vị trí khác nhau.

Scoring

  • Subtask ( số điểm): và .
  • Subtask ( số điểm): Không có giới hạn bổ sung.

Example

Test 1

Input

aaaa
3
a
aa
aaa

Output

7

Giải thích: Các độ dài từ có thể chọn là hoặc . Bảy cách phân tích độ dài là , ba hoán vị của , hai hoán vị của , và .

Lời giải tóm tắt
  • Ý tưởng: Chèn từ điển vào Trie. Với dp[i] là số cách ghép s[0..i-1], từ mỗi i duyệt Trie theo s[i..] và cộng dp[i] vào điểm kết thúc của mọi từ gặp được.
  • Tính đúng đắn: Mỗi cách ghép tiền tố s[0..j] có một vị trí cắt cuối i duy nhất và từ cuối s[i..j] thuộc từ điển. dp[i] đếm mọi phần trước, Trie liệt kê đúng mọi từ có thể bắt đầu tại i, nên mỗi cách được cộng đúng một lần và không cách nào bị bỏ sót.
  • Độ phức tạp: Xây Trie tốn O(S_dict). Phần DP tốn O(|s|·M) trong cận xấu nhất, với M là độ dài từ dài nhất có thể khớp; bộ nhớ O(|s|+S_dict).
  • Đối chứng nhỏ: Dùng DP nhưng ở mỗi vị trí quét trực tiếp toàn bộ từ điển và so sánh ký tự để tìm các từ khớp. Đây là mô hình độc lập được dùng cho mười test nhỏ.