canuc80k7306·7/40

Ghép Chuỗi Bằng Từ Điển

Nộp bài trên LQDOJ

Bài 73 · Aho Corasick

Một cách ghép xâu là một dãy từ trong từ điển mà khi nối theo đúng thứ tự sẽ thu được toàn bộ xâu đích. Mỗi ký tự phải thuộc đúng một từ và không được bỏ qua ký tự nào.

Đếm số cách chia toàn bộ xâu đích thành một dãy từ trong từ điển, giữ nguyên thứ tự ký tự. Hai cách khác nhau khi tập vị trí cắt của chúng khác nhau.

Input

  • Dòng đầu chứa xâu đích .
  • Dòng thứ hai chứa số nguyên , số từ trong từ điển.
  • dòng tiếp theo chứa các từ của từ điển.

Output

  • In số cách ghép từ các từ trong từ điển, lấy phần dư theo .

Constraints

  • .
  • .
  • và mọi từ chỉ gồm các chữ cái thường đến .
  • Các từ trong từ điển đôi một khác nhau.
  • Tổng độ dài từ không quá .

Scoring

  • Subtask ( điểm): test nhỏ, phù hợp với lời giải trực tiếp theo định nghĩa.
  • Subtask ( điểm): test không có giới hạn bổ sung.

Example

Test 1

Input

ba
3
b
a
ba

Output

2

Giải thích: Có hai cách tạo ba: dùng trực tiếp từ ba, hoặc ghép rồi .

Lời giải tóm tắt
  • Ý tưởng: Xây Aho-Corasick cho từ điển. Khi đọc đến vị trí i, mọi terminal trên chuỗi output link là một lựa chọn từ cuối; cộng dp[i+1-|w|] vào dp[i+1].
  • Tính đúng đắn: Mỗi cách ghép một tiền tố có duy nhất một từ cuối. Automaton liệt kê đúng mọi từ có occurrence kết thúc tại vị trí đang xét, còn dp đếm đúng mọi cách ghép phần đứng trước; các nhóm theo từ cuối rời nhau và phủ hết đáp án.
  • Độ phức tạp: O(L + |s| + Z) thời gian, với Z là tổng số từ điển kết thúc tại các vị trí được quét; O(L + |s|) bộ nhớ.