Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)

164 views

Published on

2018/9/21 会津大学プログラミング合宿 Day3 (北大セット) G 問題
※文字が見えない場合、ダウンロードするかフルスクリーンにしてご覧ください。(フルスクリーンにすると文字が消える問題に対処できるようです)

Published in: Technology
  • Be the first to comment

  • Be the first to like this

ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)

  1. 1. 会津合宿 2018 Day3 G 問題 回文部分列 (Palindromic Subsequences) 原案: tsutaj 問題文: tsutaj 解答: tsutaj・kazu・tsukasa_diary 解説: tsutaj 2018 年 9 月 21 日 tsutaj ACPC 2018 Day3 G 2018/9/21 1 / 12
  2. 2. 問題 回文部分列 (Palindromic Subsequences) 文字列 S が与えられる S の連続とは限らない部分文字列であって回文であるものは何種類? 制約 1 ≤ |S| ≤ 2, 000 S は英小文字のみからなる 例 acpc に含まれる回文部分列は 5 種類 a, c, cc, cpc, p それぞれの回文は unique に数える tsutaj ACPC 2018 Day3 G 2018/9/21 2 / 12
  3. 3. 回文の性質 回文はどんな性質がある? tsutaj ACPC 2018 Day3 G 2018/9/21 3 / 12
  4. 4. 回文の性質 回文はどんな性質がある? 右から読んでも左から読んでも同じ 文字列の前半を T、T を左右反転させた文字列を T′ とおくとき、回文 S は T + (中心の文字) + T′ の形をしている tsutaj ACPC 2018 Day3 G 2018/9/21 3 / 12
  5. 5. 方針 T としてあり得るものが何種類あるのかを知りたい tsutaj ACPC 2018 Day3 G 2018/9/21 4 / 12
  6. 6. 方針 T としてあり得るものが何種類あるのかを知りたい T′ は T を反転させたものなので、S を左から走査してできる部分列 と、S を右から走査してできる部分列が一致する状況を数え上げたい tsutaj ACPC 2018 Day3 G 2018/9/21 4 / 12
  7. 7. 方針 T としてあり得るものが何種類あるのかを知りたい T′ は T を反転させたものなので、S を左から走査してできる部分列 と、S を右から走査してできる部分列が一致する状況を数え上げたい T および T′ の終端の位置がわかれば、中心の文字としてあり得るも のの種類数も数えられる tsutaj ACPC 2018 Day3 G 2018/9/21 4 / 12
  8. 8. 方針 S の他に、S を反転させた文字列 S′ も用意 tsutaj ACPC 2018 Day3 G 2018/9/21 5 / 12
  9. 9. 方針 S の他に、S を反転させた文字列 S′ も用意 T および T′ を求めることは、S と S′ の共通部分列を求めることと 同じ! ただし区間被りに注意すること tsutaj ACPC 2018 Day3 G 2018/9/21 5 / 12
  10. 10. 共通部分列 2 つの文字列に対する共通部分列の種類数はどのように数え上げる? tsutaj ACPC 2018 Day3 G 2018/9/21 6 / 12
  11. 11. 共通部分列 2 つの文字列に対する共通部分列の種類数はどのように数え上げる? DP をしよう! 説明の都合上、2 つの文字列を X, Y と置く tsutaj ACPC 2018 Day3 G 2018/9/21 6 / 12
  12. 12. 共通部分列 2 つの文字列に対する共通部分列の種類数はどのように数え上げる? DP をしよう! 説明の都合上、2 つの文字列を X, Y と置く dp[i][j] := X の i 文字目、Y の j 文字目まで使ってできる共通部分列 の種類数 状態 dp[i][j] で考慮している共通部分列の末尾にアルファベット c を追 加するときは、X の i 文字目より後の c の中で最も近いもの・Y の j 文字目より後の c の中で最も近いものを選んで遷移すれば良い tsutaj ACPC 2018 Day3 G 2018/9/21 6 / 12
  13. 13. 共通部分列 2 つの文字列に対する共通部分列の種類数はどのように数え上げる? DP をしよう! 説明の都合上、2 つの文字列を X, Y と置く dp[i][j] := X の i 文字目、Y の j 文字目まで使ってできる共通部分列 の種類数 状態 dp[i][j] で考慮している共通部分列の末尾にアルファベット c を追 加するときは、X の i 文字目より後の c の中で最も近いもの・Y の j 文字目より後の c の中で最も近いものを選んで遷移すれば良い 次ページで詳しく解説 tsutaj ACPC 2018 Day3 G 2018/9/21 6 / 12
  14. 14. 共通部分列 dp[2][1] の状態から、共通部分列を 1 文字増やしたい 's' を増やしたい場合、どの s を持ってくればよいか? tsutaj ACPC 2018 Day3 G 2018/9/21 7 / 12
  15. 15. 共通部分列 こういうとり方もあり得るが・・・ tsutaj ACPC 2018 Day3 G 2018/9/21 8 / 12
  16. 16. 共通部分列 この方が余りが多くて余裕がある! 余りが多いと、より長い共通部分列を作れる可能性がある tsutaj ACPC 2018 Day3 G 2018/9/21 9 / 12
  17. 17. 共通部分列 この方が余りが多くて余裕がある! 余りが多いと、より長い共通部分列を作れる可能性がある なので、文字を増やす際は近いものを貪欲に取り、余りを増やしたほ うが良い この DP によって、共通部分列を unique に数え上げることができる tsutaj ACPC 2018 Day3 G 2018/9/21 9 / 12
  18. 18. 解法の流れ 回文部分列の数え上げは以下のように解ける tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  19. 19. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  20. 20. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる dp[i][j] の中で区間として被らないものについて、dp[i][j]× (余った区 間内にあるアルファベットの種類数 +1) を計算して答えに足し合わ せる tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  21. 21. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる dp[i][j] の中で区間として被らないものについて、dp[i][j]× (余った区 間内にあるアルファベットの種類数 +1) を計算して答えに足し合わ せる 余った区間内にあるアルファベットの種類数を掛けるのは、奇数長の回 文を数え上げるため 間に 1 文字挟むと奇数長回文になる tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  22. 22. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる dp[i][j] の中で区間として被らないものについて、dp[i][j]× (余った区 間内にあるアルファベットの種類数 +1) を計算して答えに足し合わ せる 余った区間内にあるアルファベットの種類数を掛けるのは、奇数長の回 文を数え上げるため 間に 1 文字挟むと奇数長回文になる +1 するのは、偶数長の回文を数え上げるため 間になにも挟まないと偶数長回文になる tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  23. 23. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる dp[i][j] の中で区間として被らないものについて、dp[i][j]× (余った区 間内にあるアルファベットの種類数 +1) を計算して答えに足し合わ せる 余った区間内にあるアルファベットの種類数を掛けるのは、奇数長の回 文を数え上げるため 間に 1 文字挟むと奇数長回文になる +1 するのは、偶数長の回文を数え上げるため 間になにも挟まないと偶数長回文になる 空文字列を誤って答えに足さないよう注意! 最後に −1 するか、例外処理するか、お好みで tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  24. 24. 解法の流れ 回文部分列の数え上げは以下のように解ける 先ほどの共通部分列の DP をやる dp[i][j] の中で区間として被らないものについて、dp[i][j]× (余った区 間内にあるアルファベットの種類数 +1) を計算して答えに足し合わ せる 余った区間内にあるアルファベットの種類数を掛けるのは、奇数長の回 文を数え上げるため 間に 1 文字挟むと奇数長回文になる +1 するのは、偶数長の回文を数え上げるため 間になにも挟まないと偶数長回文になる 空文字列を誤って答えに足さないよう注意! 最後に −1 するか、例外処理するか、お好みで 足しあわせた結果が答え tsutaj ACPC 2018 Day3 G 2018/9/21 10 / 12
  25. 25. 計算量 この解法の計算量は? tsutaj ACPC 2018 Day3 G 2018/9/21 11 / 12
  26. 26. 計算量 この解法の計算量は? 共通部分列 DP は「インデックス i より後に登場するアルファベット c の中で最も近いものはどれか」を前処理することで O(|S|2) 前処理は線形でも可能だし二乗でも可能 どちらを書いても構いません tsutaj ACPC 2018 Day3 G 2018/9/21 11 / 12
  27. 27. 計算量 この解法の計算量は? 共通部分列 DP は「インデックス i より後に登場するアルファベット c の中で最も近いものはどれか」を前処理することで O(|S|2) 前処理は線形でも可能だし二乗でも可能 どちらを書いても構いません 答えを足し合わせる時は、「指定区間内にアルファベットは何種類ある か」を前処理することで O(|S|2) 各アルファベットについて累積和を用意すれば、何種類あるかは O(1) 足し合わせるときに参照する場所の候補が O(|S|2 ) なので、この処理は 全体で O(|S|2 ) tsutaj ACPC 2018 Day3 G 2018/9/21 11 / 12
  28. 28. 計算量 この解法の計算量は? 共通部分列 DP は「インデックス i より後に登場するアルファベット c の中で最も近いものはどれか」を前処理することで O(|S|2) 前処理は線形でも可能だし二乗でも可能 どちらを書いても構いません 答えを足し合わせる時は、「指定区間内にアルファベットは何種類ある か」を前処理することで O(|S|2) 各アルファベットについて累積和を用意すれば、何種類あるかは O(1) 足し合わせるときに参照する場所の候補が O(|S|2 ) なので、この処理は 全体で O(|S|2 ) したがって問題全体で O(|S|2) で解ける! tsutaj ACPC 2018 Day3 G 2018/9/21 11 / 12
  29. 29. Writer 解・統計 Writer 解 tsutaj (C++・78 行・1985 bytes) kazu (C++・83 行・2329 bytes) tsukasa_diary (C++・60 行・1422 bytes) 統計 AC / tried: 11 / 15 (73.3 %) First AC On-site: acpc_aizulim (79 min) On-line: LLma (23 min) tsutaj ACPC 2018 Day3 G 2018/9/21 12 / 12

×