├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── algorithm.md │ └── issue.md └── workflows │ ├── build.yml │ ├── lint.yml │ └── python.yml ├── .gitignore ├── CONTRIBUTING.md ├── DESIGN.md ├── Gemfile ├── README.md ├── _algorithms ├── aho-corasick.md ├── auxiliary-tree.md ├── beam-search.md ├── bellman-ford.md ├── bfs.md ├── binary-exponentiation.md ├── binary-search.md ├── boruvka.md ├── boyer-moore-horspool.md ├── boyer-moore-majority-vote-algorithm.md ├── boyer-moore.md ├── centroid-decomposition.md ├── chinese-remainder-theorem.md ├── chirp-z-transform.md ├── chokudai-search.md ├── chu-liu-edmonds.md ├── coordinate-compression.md ├── cumulative-sum.md ├── d-edge-shortest-path-monge.md ├── dfs.md ├── dial.md ├── dijkstra.md ├── dinic.md ├── doubling.md ├── dsu-on-tree.md ├── dynamic-programming.md ├── eppstein-algorithm.md ├── euclidean-algorithm.md ├── fast-fourier-transform.md ├── fast-kitamasa-method.md ├── fast-zeta-transform.md ├── ford-fulkerson.md ├── garner-algorithm.md ├── heavy-light-decomposition.md ├── hill-climbing.md ├── imos-method.md ├── inclusion-exclusion-principle.md ├── johnson-algorithm.md ├── karatsuba-algorithm.md ├── kitamasa-method.md ├── knuth-morris-pratt.md ├── knuth-yao-speedup.md ├── kruskal.md ├── lagrange-interpolation.md ├── manacher.md ├── meet-in-the-middle.md ├── mo-algorithm.md ├── monotone-minima.md ├── montgomery-multiplication.md ├── number-theoretical-transform.md ├── polynomial-interpolation-geometric.md ├── prim.md ├── rabin-karp.md ├── recursive-descent.md ├── rerooting.md ├── sieve-of-eratosthenes.md ├── simulated-annealing.md ├── smawk-algorithm.md ├── spfa.md ├── sqrt-decomposition.md ├── strongly-connected-components.md ├── two-pointers.md ├── warshall-floyd.md ├── weighted-union-heuristic.md ├── yen-algorithm.md └── z-algorithm.md ├── _config.yml ├── _layouts ├── default.html └── entry.html ├── _sass ├── rating-colors.scss ├── style.scss └── user-colors.scss ├── _tenkeis ├── 45-rotation.md ├── bininary-search-the-answer.md ├── bitmask-dp.md ├── counting-by-complement.md ├── event-sort.md ├── gyaku-shori.md ├── gyou-retsu-tyouten.md ├── hakoneekiden-dp.md ├── in-place-dp.md ├── kakuchou-graph.md ├── keta-dp.md ├── kihonteiri-kityaku.md ├── min-saiki-bunkatsu.md ├── modosu-dp.md ├── nijou-ki-dp.md ├── product-bunkai.md ├── separation-of-variables.md ├── snakes.md └── tanten-renketsu.md ├── assets ├── css │ └── style.scss └── img │ ├── .gitignore │ ├── README.md │ ├── virtual-tree-example-in.dot │ ├── virtual-tree-example-in.svg │ ├── virtual-tree-example-out.dot │ └── virtual-tree-example-out.svg ├── index.md ├── scripts ├── lint.py ├── requirements.txt └── user-ratings.py ├── template.md └── tenkei └── index.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.md] 10 | indent_style = space 11 | 12 | [*.py] 13 | indent_style = space 14 | indent_size = 4 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ページを追加する 3 | about: アルゴリズムなどについてのページを追加したいときはここから 4 | title: "[アルゴリズム] (ここにアルゴリズム名などを書く)" 5 | labels: "algorithm" 6 | assignees: "" 7 | --- 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 問題を報告する 3 | about: なにか問題を見つけたときはここから 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout repository 11 | uses: actions/checkout@v2 12 | 13 | - name: Set up Ruby 14 | uses: actions/setup-ruby@v1 15 | 16 | - uses: actions/cache@v2 17 | with: 18 | path: .vendor/bundle 19 | key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} 20 | restore-keys: | 21 | ${{ runner.os }}-gems- 22 | 23 | - name: Bundle install 24 | run: bundle install --path .vendor/bundle --jobs 4 --retry 3 25 | 26 | - name: Build the site 27 | run: bundle exec jekyll build 28 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout repository 10 | uses: actions/checkout@v2 11 | 12 | - name: Set up Python 3.9.15 13 | uses: actions/setup-python@v2 14 | with: 15 | python-version: 3.9.15 16 | 17 | - name: Install dependencies 18 | run: pip3 install -r scripts/requirements.txt 19 | 20 | - name: Run scripts/lint.py 21 | run: python3 scripts/lint.py 22 | -------------------------------------------------------------------------------- /.github/workflows/python.yml: -------------------------------------------------------------------------------- 1 | name: python 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | python: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | 12 | - name: Set up Python 13 | uses: actions/setup-python@v1 14 | with: 15 | python-version: 3.9.16 16 | 17 | - name: Install dependencies 18 | run: pip3 install -r scripts/requirements.txt 19 | 20 | - name: Run isort 21 | run: isort --check-only --diff scripts/*.py 22 | 23 | - name: Run yapf 24 | run: | 25 | yapf --diff '--style={ COLUMN_LIMIT: 9999 }' scripts/*.py 26 | 27 | - name: Run mypy 28 | run: mypy scripts/*.py 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Jekyll 2 | _site/ 3 | .sass-cache/ 4 | .jekyll-cache/ 5 | .jekyll-metadata 6 | 7 | # Ruby 8 | /.bundle/ 9 | /.vendor/ 10 | # In general you should check-in Gemfile.lock but we would not like to check-in in this repository. See https://github.com/kmyk/algorithm-encyclopedia/pull/136 11 | Gemfile.lock 12 | 13 | # backup files which `scripts/lint.py --fix` generates 14 | *~ 15 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING.md 2 | 3 | ## 編集方法について 4 | 5 | ### 記事を修正するには 6 | 7 | 修正方法が明らかなものならプルリクエストを送ってください。 8 | 簡単には修正できないものなら issue を立ててください。 9 | それぞれページの右下の「Edit this page」「Report issues」というリンクを使うと便利です。 10 | 11 | 12 | ### 記事に加筆するには 13 | 14 | プルリクエストを送ってください。 15 | そうすることで記事がより良くなるのであれば、記事の元々の文章を削除したり構成を変更したりしても構いません。 16 | 17 | プルリクエストを送る際には、過去のすべての authors と reviewers にメンションを飛ばしてください。 18 | 19 | 20 | ### 記事を追加するには (概要のみ) 21 | 22 | [トップページ](https://noshi91.github.io/algorithm-encyclopedia/) の目次にのみ項目を追加する場合は以下のようにします。 23 | 24 | 1. [_algorithms/](https://github.com/kmyk/algorithm-encyclopedia/tree/gh-pages/_algorithms) ディレクトリの中に Markdown ファイルを追加する。 25 | - [template.md](https://raw.githubusercontent.com/kmyk/algorithm-encyclopedia/gh-pages/template.md) をコピペしてくればよい 26 | 1. 追加した Markdown ファイルを編集する。 27 | 1. プルリクエストを送る。 28 | 29 | 30 | ### 記事を追加するには (本文含む) 31 | 32 | 個別の記事ページ ([例](https://noshi91.github.io/algorithm-encyclopedia/monotone-minima)) を追加する場合は以下のようにします。 33 | 34 | 1. 対応する issue を作る。 35 | - 「[ページを追加する](https://github.com/online-judge-tools/verification-helper/issues/new?template=algorithm.md)」のテンプレートを使う。中身は空でよい 36 | - 衝突を防ぐため、ページ作成の作業をすることを宣言するのがよい 37 | 1. 上記の「記事を追加する (概要のみ)」と同様にして、トップページの目次に項目を追加する。 38 | 1. 対応する項目の Markdown ファイルに本文を追加する。 39 | 1. プルリクエストを送る。 40 | 41 | 42 | ### authors と reviewers 43 | 44 | 記事には authors と reviewers が表示されます。 45 | ある記事のある変更について、author とはその変更を書いた人のことであり、reviewer とはその変更をレビューした人のことです。 46 | 47 | authors と reviewers を表示することは、その人たちがその記事への貢献をしたことを読者に伝える意味があります。 48 | authors や reviewers として名前を乗せることは、基本的には authors や reviewers にとって利益 (つまり、読者から「あの人が書いてくれた記事は参考になるなあ」などの良い印象を持たれる) になります。 49 | ただし、記事に重大な問題があった場合などには不利益 (つまり、読者から「あの人の書いた記事は不正確で困るなあ」などの悪い印象を持たれる) になる可能性もあることは認識しておくべきでしょう。 50 | 51 | authors や reviewers に名前が乗っていることは、その人たちがその記事の内容全体に責任を負っていることは意味しません。 52 | その人たちが責任を負うのは、その人たちが関与した変更のみです。 53 | 誤字や脱字などの自明な修正であれば、authors や reviewers への確認なしに勝手に記事が修正されるかもしれません。 54 | authors や reviewers と連絡が取れない場合は、その人たちの確認なしに非自明な内容の追加や削除がされるかもしれません。 55 | 後から記事が変更されたとき、それによって発生した問題によって元々の authors や reviewers が不利益を被ることを防ぐために、表示は「その記事の authors / reviewers」ではなく「その記事ある変更の authors / reviewers」という形でなされます。 56 | 57 | 完全な編集履歴は commit log から閲覧することができます。 58 | しかし、GitHub 上へ移動して commit log を確認するのは面倒であり、たいていの読者はこれを確認しないでしょう。 59 | authors と reviewers の表示は、commit log を確認しない読者に対しても、誰がその記事に貢献したのかを分かりやすく伝える効果があります。 60 | 61 | 62 | ### メタデータの仕様 63 | 64 | [front matter](http://jekyllrb-ja.github.io/docs/front-matter/) に書くべき情報は以下の通りです。 65 | 66 | - `layout`: 常に `entry` 67 | - `changelog` (辞書の配列): そのページの更新履歴 68 | - `summary`: その更新の内容の概要 69 | - `authors`: その更新をした人たちの名前 (AtCoder ID) 70 | - `reviewers` (空欄可): その更新をレビューした人たちの名前 (AtCoder ID) 71 | - `date`: その更新をした日時 ([ISO 8601](https://ja.wikipedia.org/wiki/ISO_8601) で秒まで) (例: `2020-07-09T00:00:00+09:00`)。`$ date --iso-8601=seconds` を実行するとよい。時間や分や秒は適当でも (たとえばすべて 0 でも) 構わない。 72 | - `algorithm` (空欄可): アルゴリズムについての概要 73 | - `input` (空欄可): アルゴリズムへの入力 74 | - `output` (空欄可): アルゴリズムからの出力 75 | - `time_complexity` (空欄可): アルゴリズムの時間計算量 76 | - `space_complexity` (空欄可): アルゴリズムの空間計算量 77 | - `aliases` (空欄可): アルゴリズムの別名の列 78 | - `level` (空欄可): アルゴリズムの知名度。難しさは判定しにくいので有名さ (競プロでどのくらいよく使われるか) を使う。「この色の人ならみんな知っていそうだな (主観)」という色を書く。赤でも知らなさそうなものは黒 (`black`) とする。 79 | - `description`: アルゴリズムの概要。「(ここにアルゴリズムの名前が入る)とは、(ここにアルゴリズムの概要が入る)というアルゴリズムである。」という形の文から初めて数文ぐらいで書くのがよい。KaTeX は使用可。HTML も使用可だがあまり推奨されない。 80 | - `draft` (省略可): これが `true` であるとトップページから記事ページへのリンクが貼られない。 81 | - `draft_urls` (省略可): 記事の本文の代わりになるリンク (複数可) 82 | 83 | 84 | ### 数式 85 | 86 | 数式には [KaTeX](https://katex.org/) が使えます。KaTeX が対応している関数の一覧は [Supported Functions](https://katex.org/docs/supported.html) にあります。 87 | 88 | [コードブロック](https://docs.github.com/ja/github/writing-on-github/creating-and-highlighting-code-blocks)中で数式を利用したい場合は言語名に `plaintext-katex` を指定してください。 89 | 90 | 91 | ### AtCoder ID 92 | 93 | Markdown 中に `chokudai` のように AtCoder ID を書くと、その AtCoder ID は highest の色で表示されます。 94 | 競技プログラマの名前を記述するときはこれを利用してください。 95 | 96 | 色の情報は [_sass/user-colors.scss](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/_sass/user-colors.scss) ファイルに CSS として保存されています。このファイルは [scripts/user-ratings.py](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/scripts/user-ratings.py) によって生成されます。定期的に `$ python3 scripts/user-ratings.py` を実行して色の情報のファイルを更新してください。 97 | 98 | 99 | ## 画像ファイル 100 | 101 | [`assets/img/`](https://github.com/kmyk/algorithm-encyclopedia/tree/gh-pages/assets/img) に置いてください。 102 | また、後から画像を修正する必要が発生したときのために、画像の編集方法を [`assets/img/README.md`](https://github.com/kmyk/algorithm-encyclopedia/tree/gh-pages/assets/img/README.md) に書いておいてください。 103 | 104 | ### ローカルでの記事の閲覧 105 | 106 | ローカルで記事を閲覧するには、以下のコマンドを順に実行してください。HTTP サーバが建ち から閲覧できます。 107 | 108 | ``` console 109 | $ git clone https://github.com/noshi91/algorithm-encyclopedia 110 | $ cd algorithm-encyclopedia 111 | $ sudo apt install ruby-all-dev ruby-bundler 112 | $ bundle install --path .vendor/bundle 113 | $ bundle exec jekyll serve --incremental 114 | ``` 115 | 116 | 117 | ### ローカルでのテストの実行 118 | 119 | GitHub Actions を利用して、典型的なミスが機械的に検出されるよう設定されています。 120 | このテストをローカルで実行するには、以下のコマンドを順に実行してください。 121 | 122 | ``` console 123 | $ pip3 install -r scripts/requirements.txt 124 | $ python3 scripts/lint.py 125 | ``` 126 | 127 | また `--fix` オプションを付けて実行 (`$ python3 scripts/lint.py`) すると自動で修正できるミスは自動で修正してくれます。 128 | 129 | テスト ([`scripts/lint.py`](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/scripts/lint.py)) には気軽に変更を加えてしまって構いません。 130 | このテストは記事を書く人の快適さを目的として用意されています。 131 | 記事の内容に制限をかけることはその手段でしかありません。 132 | 記事でなくテストの側が不適切であるためにテストが失敗になってしまっているときは、テストの側を修正して成功にしてください。 133 | 記事を書いている上で気付いた典型的なミス (例: `有向グラフ` を `有効グラフ` と typo してしまう) は、テストに検出処理を追加できそうなら追加しておいてください。 134 | 135 | 136 | ### 複製の公開 137 | 138 | このリポジトリの fork を作ったあと、そのリポジトリで GitHub Pages を有効にしてください ([GitHub Pages サイトの公開元を設定する - GitHub Docs](https://docs.github.com/ja/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site))。fork では自動的には GitHub Pages が有効にならないことに注意してください。 139 | 実際に公開した例は にあります。 140 | 141 | 通常の GitHub 上では Markdown ファイル中の数式をプレビューできないという問題があるため、プルリクエストを出す際にはこのような複製を準備して完全な形のものを閲覧できるようにしておくとスムーズでしょう。 142 | 143 | なお、GitHub Pages に公開された複製からは自動で へのリダイレクトが発生するようになっています。 144 | これは、本体のリポジトリの GitHub Pages とテスト用の複製の GitHub Pages との間での、どれが本体なのか分からないという混乱の発生を防ぐための措置です。 145 | 本体のリポジトリへリダイレクトされない完全な fork を作りたいときは、`_config.yml` や `CNAME` を編集することでこの挙動を修正できます。 146 | 147 | 148 | ## どのような内容についての記事が掲載されるか 149 | 150 | ### 記事が説明する対象の種類について 151 | 152 | 競技プログラミングに関連する知識であって、アルゴリズムや数学の知識を取り扱います。 153 | そのような知識の例は以下のようになります。 154 | 155 | - 個別のアルゴリズムやデータ構造 156 | - 例: Dijkstra 法 157 | - 例: 単体法 158 | - アルゴリズムやデータ構造の分類 159 | - 例: 動的計画法 160 | - 例: 線型計画法 161 | - アルゴリズム的な問題 162 | - 例: 巡回セールスマン問題 163 | - 例: 線型計画問題 164 | - 個別の数学的対象 165 | - 例: ピーターセングラフ 166 | - 数学的対象のクラス 167 | - 例: モノイド 168 | - 例: 単調な数列 169 | - 数学的性質 170 | - 例: 線形性 171 | - 例: 数列の単調性 172 | - 数学的事実 173 | - 例: 最小カット最大フロー定理 174 | 175 | どれに含めればよいか分かりにくい対象もあります (たとえば「木の直径」は性質と見るべきか対象と見るべきか曖昧でしょう) が、そのような対象についての記事であってもかまいません。 176 | 177 | データ構造については[データ構造Wiki](https://scrapbox.io/data-structures/) への寄稿も検討してみてください。 178 | 179 | 上記のものに含められないような知識については[典型テク版のページ](https://dic.kimiyuki.net/tenkei/)に隔離した形で掲載します。 180 | そのような知識の例は以下のようになります。 181 | 182 | - 考察テク 183 | - 例: 完全グラフや星グラフのような極端な場合を考えるとよい 184 | - 典型パターン 185 | - 例: クエリ列を処理するときは逆から考えるとうまくいくことがある 186 | - 実装テク 187 | - 例: 閉区間でなく半開区間を使うと実装が楽になる場合が多い 188 | - 個別のプログラミング言語についての知識 189 | - 例: C++ の `std::cin` は何も考えずに使うと Codeforces では TLE することがある 190 | 191 | 192 | ### 記事が説明する対象の難易度や知名度について 193 | 194 | 基本的には、どんな難易度や知名度の知識についての記事であっても掲載します。 195 | 特に、実際の競プロではほとんど出現しないようなマイナーな知識についても積極的に掲載していく方針です。 196 | 最も記載したいものは「現在はほとんど知られていないが、将来的には典型となるであろう知識」です。 197 | 198 | ただし、十分に広く知られておりかつ競プロに特有ではない知識 (例: 三角関数) についての記事は、内容次第ではメンテコストの都合から掲載を見合わせる可能性はあります。 199 | 200 | 201 | ## どのように記事を書くべきか 202 | 203 | ### 何について語っているかを明確にする 204 | 205 | あなたが説明しようとしているものが何であるかについて、明確に説明してください。 206 | たとえばそれが「あるひとつの具体的なアルゴリズム」であるのか「ある性質を満たすアルゴリズムの総称」であるのか「何らかの形の問題」であるのかについて自覚的に書いてください。 207 | 208 | 可能なら厳密な特徴付けを与えてください。 209 | 性質や利用方法や具体例は定義ではありません。 210 | 「条件 P を満たすものは A である」という説明では A を説明したことにはなりません。 211 | 「条件 Q を満たすものは A であり、条件 Q を満たさないものは A ではない」ということまで説明する必要があります。 212 | すべてのアルゴリズムとデータ構造について、明確にそれが何であるかを特徴付けられるとは限りませんが、できる限り説明するようにしてください。具体例をいくつか列挙するだけにして正確なところは読者が察するのを期待するという書き方は避けてください。 213 | 214 | たとえば「阪本さんとは誰ですか?」と聞かれたとき、どのように答えるのがよいでしょうか? 215 | 「かわいいです」とか「関西弁を話します」というのは答えになっていません。 216 | 「黒いねこです」という答えも不十分です。 217 | 黒いねこであることは坂本さんの代表的な性質のひとつかもしれませんが、黒いねこは坂本さんではありません。 218 | 「○○研究所で飼われているある黒猫です」のように個体を特定して答える必要があります。 219 | 220 | たとえば「累積和とは何ですか?」と聞かれたときも同様です。 221 | 「配列上の区間の総和を求めることができます」というのは累積和の利用例のひとつでしかなく、累積和そのものの説明ではありません。 222 | 累積和を利用する問題をひとつ選んで例として紹介して「累積和はこのように使います」とするのでも同じです。まずは「a を数列とするとき、a に対する累積和とは、bᵢ = a₀ + a₁ + ⋯ + aᵢ₋₁ で定まるような数列 b のことである」のように説明してください。利用方法や具体例は定義ではありません。もちろん、その後に利用方法を説明する必要はありますし、具体例を挙げることは理解を助けるでしょう。 223 | 224 | 225 | ### それが何をするのかを明確にする 226 | 227 | あなたが説明しようとしているものが何をするのかについて、明確に説明してください。 228 | アルゴリズムについて説明する時は、そのアルゴリズムが「どのような問題を解くのか」を宣言してください。 229 | あるいは「入力」「出力」「計算量」を明示してください。 230 | 231 | 232 | ### 他の事柄との関係を明確にする 233 | 234 | あなたが説明しようとしているものが他のものとどのように関連しているかについて、説明を与えてください。 235 | 「関連項目」などの節を作り、その中に列挙するのでもよいでしょう。 236 | 237 | 238 | ### 意見を書くときはそれが誰の意見なのかを明確にする 239 | 240 | 事実と意見は区別してください。広く共有されているわけではない主観的な意見を書くときは、それが誰の意見なのかを明確にしてください。 241 | 特になにか過激な意見を主張したいときは、その意見はひとまず自分のブログに書き、「外部リンク」などの節の中から参照するのがよいでしょう。 242 | 243 | 244 | ### 他: 管理コストを下げる 245 | 246 | - 他の記事に書かれた細部に直接依存することは避ける。記事同士を疎結合に保ち、ある記事の編集が他の記事に影響しないようにする。 247 | - リンクを張るときはリンク先の永続性に注意する。特に他人のブログ記事や競プロライブラリへのリンクを貼るときは [Internet Archive](https://archive.org/web/) によるスナップショットを取っておく ([Save Page Now - Wayback Machine](https://web.archive.org/save/))。 248 | - リンクを張るときはリンク先との関係が分かるようにする。例題を紹介するならば簡単な解説を書いておく。記事を紹介するならばなぜ他の記事でなくその記事が選ばれているのか分かるようにしておく。 249 | - ソースコードはそのままコピペして動くものを載せる。ソースコードの妥当性は簡単に検証できるようにしておく。 250 | - 画像ファイルは後から他の人が修正しやすいような形式を選び、修正方法のドキュメントを残しておく。 251 | 252 | 253 | ## ライセンスについて 254 | 255 | 書かれたページは [Creative Commons Attribution 4.0 International License (CC BY 4.0)](http://creativecommons.org/licenses/by/4.0/) で公開されます。 256 | -------------------------------------------------------------------------------- /DESIGN.md: -------------------------------------------------------------------------------- 1 | # DESIGN.md 2 | 3 | ## Objectives 4 | 5 | 競プロ用のアルゴリズムの解説を集めた百科辞典を作ります。 6 | 7 | 8 | ## Goals 9 | 10 | - 競プロの中級者や上級者がより効率的に知識を収集管理できるようにします。 11 | - 情報が正確であること、管理が容易であること、貢献者が明示されていることの、すべてを同時に目指します。 12 | 13 | 14 | ## Non-Goals 15 | 16 | - 競プロの初心者のための教科書を作るのではありません。 17 | - 学術のための資料を作るのではありません。 18 | 19 | 20 | ## Background 21 | 22 | ### 解決したい課題について 23 | 24 | 競プロ界隈では個人ブログが広く用いられていますが、これには「内容が古くなったまま残りやすい」「間違いが修正されにくい」「情報が散らばりやすい」「管理コストが管理者個人に集中する」などの問題があります。より効率的な知識の集積のため、この問題の解決を目指します。 25 | 26 | 27 | ## Overview 28 | 29 | Markdown で記事を書き GitHub で管理し、GitHub Pages により公開します。議論は GitHub の Issues で、編集やレビューは GitHub 上でのプルリクエストで行います。 30 | 31 | 32 | ## Detailed Design 33 | 34 | ### 比較: 情報の発信や管理のためのツールについて 35 | 36 | 競プロ界隈で用いられる情報の発信や管理のためのツールとして、代表的なものは以下のようになります。 37 | 38 | - 個人ブログ 39 | - SNS 40 | - 質問サイト 41 | - 共有 wiki 42 | - 招待制 wiki 43 | - GitHub 44 | 45 | 個人ブログについて。 46 | 「比較的簡単に利用できる」「長文や数式が書きやすい」などの長所があります。 47 | しかし、すでに述べたように、これらには「内容が古くなったまま残りやすい」「間違いが修正されにくい」「情報が散らばりやすい」「管理コストが管理者個人に集中する」などの短所があります。 48 | Codeforces のブログもここに含めて考えるべきでしょう。 49 | 50 | SNS について。 51 | コンテストの感想や数行程度の解説はたいていツイートの形で公開されます。「とても気軽に利用できる」「コメントが付けやすい」という長所と同時に「数式や長文が書きにくい」「後から内容を編集できない」「検索が難しい」「外部から閲覧できないことがある」などの短所があります。 52 | 特に Twitter が多く利用されますが、Slack や Discord が選ばれることもあります。 53 | 54 | 質問サイトについて。 55 | 質問と解答という形をとるため、個人ブログなどとは別物と考えるべきでしょう。 56 | 「自分の知りたい内容を質問できる」一方で「必ずしも解答があるとは限らない」のが特徴です。 57 | 競プロ専用のサイトとしては [procon-qa](https://procon-qa.herokuapp.com/) があります。 58 | 59 | 共有 wiki について。 60 | 「誰でも記事の追加や修正ができる」という長所はありますが「内容の正確性が保証されない」「誰が貢献したのかが不明瞭になりやすい」という短所があります。 61 | Wikipedia や [yukicoder Wiki](https://yukicoder.me/wiki) があります。 62 | 63 | 招待制 wiki にはついて。 64 | 適切に運用すれば「管理コストが特定の個人に集中しない」「レビューなどによって内容の正確性を保証できる」という長所を持ちます。 65 | [データ構造Wiki](https://scrapbox.io/data-structures/) があり、内容は充実しています。 66 | 67 | GitHub について。 68 | 広義の招待制 wiki のように使えます。「編集権限を要求しなくても編集に参加できる」「編集時のレビューを行いやすい」という長所があります。 69 | [Library-Checker](https://judge.yosupo.jp/) はとても成功した例です。 70 | 71 | 72 | ### GitHub と GitHub Pages を使う 73 | 74 | Markdown ファイルを GitHub 上で管理し、GitHub Pages を使って公開します。 75 | Jekyll をそのまま利用し、数式の表示は Jekyll で行います。 76 | 77 | GitHub と GitHub Pages を使った公開の長所としては 78 | 79 | - 「プルリクエスト経由で、誰でも自由に記事の追加や修正を提案できる」 80 | - 「プルリクエストのマージには承認が必要であり、記事の内容が保証される」 81 | - 「修正やレビューの過程や貢献者がコミットログやレビューコメントなどの中に残る」 82 | 83 | があります。これらは個人ブログの形式が抱えていた問題を解決するために役立ちます。 84 | 他にも「GitHub Actions として機械的なチェックを走らせられる」「誰でも fork してバックアップを残し複製を作れる」のような長所もあります。 85 | 86 | 一方で短所としては「数式のプレビューが Web 上ではできない」「git や GitHub の操作ができる人しか編集に参加できない」などがあります。特にプレビューの問題は重大ですが、多くの長所とのトレードオフとして受け入れることとします。 87 | 88 | 89 | ### YAML front matter を使う 90 | 91 | YAML front matter として、それぞれの記事の説明の対象についての基本的な情報を機械可読な形で記述するようにします。 92 | 書き手にとっては「最低限必要な情報が何であるかが明示される」という利点が、読み手にとっては「基本的な情報が統一的な形で提示される」という利点があります。 93 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gem "github-pages", group: :jekyll_plugins 3 | gem "jekyll-octicons", group: :jekyll_plugins 4 | gem "faraday", "< 1.0" # https://talk.jekyllrb.com/t/error-repo-pages-info-and-connectionfailed-in-layouts-default-html/3793 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kyopro Encyclopedia of Algorithms (ア辞典) 2 | 3 | 4 | 5 | ## これなに 6 | 7 | 競プロ用のアルゴリズムの解説を集めた百科辞典を目指しているサイトです。 8 | 9 | ### 内容の方針 10 | 11 | - 読者は AtCoder 黄色以上を想定しています。青色以下が黄色になるために読むものではなく、黄色や橙色が赤色以上を目指すために読むようなものを書いています。赤色以上の人が読んで面白いと感じられる内容を目指します。 12 | - 具体例を列挙して察してもらうだけは避け、それが何であるかの定義や特徴付けを与えます。それをどのように使えばよいかではなく、それが何であるかを記述します。ノウハウ本でなく辞書です。 13 | 14 | ### 編集に協力したい 15 | 16 | [CONTRIBUTING.md](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/CONTRIBUTING.md) に編集方法の説明があります。 17 | また、管理形態がなぜこうなっているのかについての説明は [DESIGN.md](https://github.com/kmyk/algorithm-encyclopedia/blob/gh-pages/DESIGN.md) にあります。 18 | -------------------------------------------------------------------------------- /_algorithms/aho-corasick.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | date: 2021-02-05T00:00:00+09:00 6 | authors: kimiyuki 7 | reviewers: 8 | - summary: 記事作成 9 | authors: kimiyuki 10 | reviewers: noshi91 11 | date: 2021-03-09T00:00:00+09:00 12 | algorithm: 13 | input: パターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ とテキスト文字列 $T$ 14 | output: パターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ のどれがテキスト文字列 $T$ に含まれるか。含まれるならその位置も求める。 15 | time_complexity: アルファベット $\Sigma$ の大きさは定数であるとして、前処理には $O(\sum \vert P_i \vert)$ で検索には $O(\vert T \vert)$ 16 | space_complexity: 17 | aliases: [] 18 | level: orange 19 | description: Aho-Corasick 法とは、複数のパターン文字列をまとめて扱える文字列検索アルゴリズムのひとつ。まず前処理として、固定された $k$ 個のパターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ たちから Trie 木を作り、その上に適切に辺を張って $O(\sum \vert P_i \vert)$ でオートマトンを作る。このオートマトンを利用して、与えられたテキスト文字列 $T$ に対して $O(\vert T \vert)$ で検索を行う。 20 | --- 21 | 22 | # Aho-Corasick 法 23 | 24 | ## 概要 25 | 26 | Aho-Corasick 法とは、複数のパターン文字列をまとめて扱える文字列検索アルゴリズムのひとつ。計算量はアルファベット $\Sigma$ の大きさにも依存するが、ここでは $\Sigma$ を固定し大きさは定数としておく。まず前処理として、固定された $k$ 個のパターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ たちから Trie 木を作り、その上に適切に辺を張って $O(\sum \vert P_i \vert)$ でオートマトンを作る。このオートマトンを利用して、与えられたテキスト文字列 $T$ に対して $O(\vert T \vert)$ で検索を行う。 27 | 28 | ## 詳細 29 | 30 | (省略) 31 | 32 | ## メモ 33 | 34 | - 計算量はアルファベット $\Sigma$ の大きさ $\sigma = \lvert \Sigma \rvert$ にも依存する。競技プログラミングにおいてはたいてい $\sigma = 26$ で定数であり、これに注意する必要はないだろう。一般の $\sigma$ が定数でない場合には、遷移関数をどのように持つかを考える必要が出てくる。これに hash map をもちいると計算量が期待計算量になり、平衡二分探索木を用いると計算量に $\log(\sigma)$ が乗る。 35 | 36 | ## 参考文献 37 | 38 | - Alfred V. Aho and Margaret J. Corasick. 1975. Efficient string matching: an aid to bibliographic search. Commun. ACM 18, 6 (June 1975), 333–340. DOI: 39 | - Aho-Crasick 法が提案された論文 40 | 41 | ## 関連項目 42 | 43 | - [Rabin-Karp 法](/algorithm-encyclopedia/rabin-karp) 44 | - Rabin-Karp 法は Aho-Corasick 法と並んで競技プログラミングでよく利用される複数パターン文字列検索アルゴリズムである。 45 | 46 | ## 外部リンク 47 | 48 | - [Aho-Corasick法 - Algoogle](https://algoogle.hadrori.jp/algorithm/aho-corasick.html)[archive.org](https://web.archive.org/web/20210311070301/https://algoogle.hadrori.jp/algorithm/aho-corasick.html) 49 | - hadrori による実装例。図付きでの解説もある。 50 | - [競技プログラミングにおける文字列アルゴリズム問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/25/005452)[archive.org](https://web.archive.org/web/20210402112827/https://blog.hamayanhamayan.com/entry/2017/03/25/005452) 51 | - hamayanhamayan によるブログ記事。例題が列挙されている。 52 | -------------------------------------------------------------------------------- /_algorithms/auxiliary-tree.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: "記事作成" 5 | authors: kimiyuki 6 | reviewers: ["MiSawa", "uwi"] 7 | date: 2021-06-17T00:00:00+09:00 8 | algorithm: 9 | input: 根付き木 $T = (V, E; r)$ とその頂点の部分集合 $X \subseteq V$ 10 | output: $X$ に含まれる頂点同士の関係を失わないように $T$ を圧縮してできる根付き木 $T'$ 11 | time_complexity: $O(\lvert V \rvert)$ で構築できる。複数の頂点の部分集合 $X_0, X_1, \dots, X _ {Q - 1}$ のそれぞれについて構築する場合でも全体で $O(\lvert V \rvert + \sum _ i \lvert X_i \rvert)$ で構築可能である。 12 | space_complexity: 13 | aliases: ["virtual tree", "auxiliary tree"] 14 | level: orange 15 | description: 与えられた根付き木 $T = (V, E; r)$ とその頂点の部分集合 $X \subseteq V$ に対し、$X$ に含まれる頂点同士の最小共通祖先関係を失わないように $T$ を圧縮して根付き木を作ることができる。なお、この木は日本の競技プログラミングの界隈では "auxiliary tree" と呼ばれることもあるが、この呼び方は推奨されない。 16 | --- 17 | 18 | # 指定された頂点たちの最小共通祖先関係を保って木を圧縮してできる補助的な木 19 | 20 | ## 概要 21 | 22 | 与えられた根付き木 $T = (V, E; r)$ とその頂点の部分集合 $X \subseteq V$ に対し、$X$ に含まれる頂点同士の子孫/祖先関係や最小共通祖先関係を失わないように $T$ を圧縮してできる補助的な根付き木 $T'$ を考えると便利であることがある。 23 | より正確には、$X$ に含まれる頂点の組 $(x, y) \in X^2$ のそれぞれに対してその最小共通祖先 $z = \mathrm{lca}(x, y)$ を考え、そのような頂点の全体 $V' = \lbrace \mathrm{lca}(x, y) \mid (x, y) \in X^2 \rbrace$ の間に元々の木 $T$ での子孫関係で辺を張ってできるものがその根付き木 $T' = (V', E'; r')$ である。 24 | 25 | この木 $T'$ は $X$ の頂点をすべて含む (つまり $X \subseteq V'$)。 26 | また $T'$ の任意の頂点 $x, y \in V'$ に対し、それらの $T$ における最小共通祖先とそれらの $T'$ における最小共通祖先とは一致する。 27 | そしてこの木 $T'$ の頂点数は $2 \lvert X \rvert - 1$ 頂点以下になることが示せる。 28 | この木の構築は単純な DFS を用いることで $O(\lvert V \rvert)$ 時間で可能である。 29 | 30 | 与えられた複数の頂点の部分集合 $X_0, X_1, \dots, X _ {Q - 1}$ のそれぞれに対しての $Q$ 個のこのような補助的な木をまとめて構成することも $K = \sum _ {i \lt Q} \lvert X_i \rvert$ に対し $O(\lvert V \rvert \log \lvert V \rvert + K \log K)$ 時間で可能である。 31 | これには sparse table などによるクエリが定数時間の LCA および Euler tour technique を用いる。 32 | 頂点の部分集合 $X_i$ はオンラインに与えられても構わない。 33 | また、LCA に構築が線型時間かつクエリが定数時間のものを用いれば $O(\lvert V \rvert + K \log K)$ 時間で、クエリがオフラインに与えられると仮定してバケットソートを利用すれば $O(\lvert V \rvert \log V + K)$ 時間で、これらの両方を用いれば $O(\lvert V \rvert + K)$ 時間での構築も可能である。 34 | 35 | たとえば、図 1 のような根付き木 $T$ からその頂点の部分集合 $X = \lbrace 7, 9, 11, 13, 14 \rbrace$ による木を作ると図 2 のようになる。 36 | 37 |
38 | 39 |
図 1. 元となる根付き木の例
40 |
41 |
42 | 43 |
図 2. 図 1 の根付き木から $X$ に属する頂点たちの最小共通祖先関係を保って木を圧縮してできる補助的な木
44 |
45 | 46 | 47 | ## 詳細 48 | 49 | 複数のこの補助的な木をまとめて構成する場合の具体的な構成方法については [LCAをベースに構築するAuxiliary Treeのメモ - 日々drdrする人のメモ](https://smijake3.hatenablog.com/entry/2019/09/15/200200)[archive.org](https://web.archive.org/web/20210512172958/https://smijake3.hatenablog.com/entry/2019/09/15/200200) を参考のこと。 50 | 51 | 52 | ## その他 53 | 54 | - 日本の競技プログラミングの界隈ではこの木が (固有名詞的に) "Auxiliary Tree" と呼ばれることがある。しかし "an auxiliary tree" とは日本語であれば「補助的な木」という程度の一般的な表現であり、これを特定の木の名前として利用することは推奨されない[^link-cut-auxiliary][^tmaehara-auxiliary]。 55 | - 中国の競技プログラミングの界隈ではこの木は「虚树」や "Virtual Tree" と呼ばれているようである[^virtual-tree]。 56 | - 英語圏の競技プログラミングの界隈においては統一された呼称はないようである[^uwi-survey]。 57 | 58 | 59 | ## 外部リンク 60 | 61 | - [LCAをベースに構築するAuxiliary Treeのメモ - 日々drdrする人のメモ](https://smijake3.hatenablog.com/entry/2019/09/15/200200)[archive.org](https://web.archive.org/web/20210512172958/https://smijake3.hatenablog.com/entry/2019/09/15/200200) 62 | - yaketake08 によるブログ記事。ある木 $T = (V, E)$ と複数の頂点の部分集合 $X_0, X_1, \dots, X _ {Q - 1}$ とが与えられたときに、それぞれの部分集合 $X_i$ に対する $Q$ 個の木をまとめて $K = \sum _ {i \lt Q} \lvert X_i \rvert$ に対し $O(\lvert V \rvert \log \lvert V \rvert + K \log K)$ で構築する方法を紹介している。 63 | - [虚树 - OI Wiki](https://oi-wiki.org/graph/virtual-tree/)[archive.org](https://web.archive.org/web/20210512172944/https://oi-wiki.org/graph/virtual-tree/) 64 | - 中国語の競技プログラミングの wiki。中国の競技プログラミングの界隈ではこの木が「虚树」や "virtual tree" と呼ばれていることが分かる。 65 | 66 | 67 | ## 注釈 68 | 69 | [^tmaehara-auxiliary]: tmaehara によるツイート: 70 | [^link-cut-auxiliary]: たとえば link-cut 木の説明では preferred edges による paths を管理する木たちが "auxiliary trees" と呼ばれることもある (例: [Link/cut tree - Wikipedia](https://en.wikipedia.org/wiki/Link/cut_tree)[archive.org](https://web.archive.org/web/20210527151259/https://en.wikipedia.org/wiki/Link/cut_tree)) 71 | [^virtual-tree]: ただし "virtual tree" という呼称が英語圏の競技プログラミングの界隈で利用されている様子はあまり見られない。"auxiliary tree" と同様に、この "virtual tree" という表現も「実質的な木」という程度の一般的な表現でしかなく、特定の木の名前として利用することは推奨されないものであるという可能性は高い。 72 | [^uwi-survey]: uwi による調査: [archive.org](https://web.archive.org/web/20210616100742/https://github.com/kmyk/algorithm-encyclopedia/issues/165#issuecomment-850781687) 73 | -------------------------------------------------------------------------------- /_algorithms/beam-search.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | date: 2021-02-28T00:00:00+09:00 6 | authors: kimiyuki 7 | reviewers: MiSawa 8 | tags: algorithm 9 | algorithm: 10 | input: 11 | output: 12 | time_complexity: 13 | space_complexity: 14 | aliases: [] 15 | level: yellow 16 | description: | 17 | ビームサーチはグラフ探索アルゴリズムのひとつである。与えられたグラフ (たいてい DAG) を初期状態となる頂点群から幅優先探索と同様に探索していくが、定数 $K$ と頂点に対する評価関数 $\varphi : V \to \mathbb{R}$ をあらかじめ固定しておき、各深さごとにその評価関数による評価値が高い順に $K$ 個のみを保持してそれ以外の頂点は無視する。$K = 1$ のときは貪欲法と一致する。焼きなまし法と並んで、ヒューリスティックコンテストで頻繁に利用されるアルゴリズムである。 18 | draft: true 19 | draft_urls: ["http://hakomof.hatenablog.com/entry/2018/12/06/000000"] 20 | --- 21 | 22 | # ビームサーチ 23 | 24 | ## 話題 25 | 26 | - 重複除去の話 27 | -------------------------------------------------------------------------------- /_algorithms/bellman-ford.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: kuretchi 7 | date: 2021-02-12T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺重み $c : E \to \mathbb{R}$ 付き有向グラフ $G = (V, E)$ および頂点 $s \in V$ 11 | output: > 12 | 各頂点 $t \in V$ に対し $s$-$t$ 最短路長 13 | time_complexity: $O(\vert V \vert \cdot \vert E \vert)$ 14 | space_complexity: 15 | aliases: [] 16 | level: cyan 17 | description: > 18 | Bellman-Ford 法とは、単一始点最短経路問題を解くアルゴリズムのひとつ。負辺があっても動作する。計算量は $O(\vert V \vert \cdot \vert E \vert)$ である。 19 | --- 20 | 21 | # Bellman-Ford 法 22 | 23 | ## 概要 24 | 25 | Bellman-Ford 法とは、単一始点最短経路問題を解くアルゴリズムのひとつ。負辺があっても動作する。 26 | ある有向辺 $(x, y)$ を使うことで頂点 $y$ への最短経路長が改善するか試し、改善するなら置き換えるという処理 (これを「緩和する」などと言う) を考える。これをすべての辺に対して行うのを 1 セットとし、これを $\vert V \vert - 1$ 回行うのが Bellman-Ford 法である。その後、負閉路が存在していなかったことの確認も行う。 27 | 計算量は $O(\vert V \vert \cdot \vert E \vert)$ である。 28 | 29 | ## 詳細 30 | 31 | (省略) 32 | 33 | ## その他 34 | 35 | - 辺の重みの正負をすべて反転させることで、単一始点最長経路問題を解くこともできる。 36 | 37 | ## 関連項目 38 | 39 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 40 | - Dijkstra 法は単一始点最短経路問題を解くアルゴリズムのひとつである。Bellman-Ford 法とは違って負辺があると動作しないが、Bellman-Ford 法より速い。 41 | - [Warshall-Floyd 法](/algorithm-encyclopedia/warshall-floyd) 42 | - Warshall-Floyd 法は全点対間最短経路問題を解くアルゴリズムのひとつである。Bellman-Ford 法と同様に、緩和を収束するまで繰り返すことで動作する。 43 | - [Shortest Path Faster Algorithm](/algorithm-encyclopedia/spfa) 44 | - Bellman-Ford 法はすべての辺について $\vert V \vert - 1$ 回ずつ緩和を行うが、これを (優先度付きではない、普通の) キューを用いて変更のあった頂点の周囲のみを緩和するように修正して高速化したものが Shortest Path Faster Algorithm である。 45 | -------------------------------------------------------------------------------- /_algorithms/bfs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["breadth-first search", "BFS"] 14 | level: green 15 | description: 幅優先探索とは、グラフや木構造の上の探索に用いられるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 幅優先探索 21 | -------------------------------------------------------------------------------- /_algorithms/binary-exponentiation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 数 $a$ および自然数 $n$ 10 | output: 累乗 $a^n$ 11 | time_complexity: $O(\log n)$ 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: 繰り返し二乗法とは、与えられた数 $a$ と自然数 $n$ に対し累乗 $a^n$ を $O(\log n)$ 回の乗算で求めるアルゴリズムのひとつ。$1 = a^0, a = a^1, a^2 = a \cdot a, a^4 = a^2 \cdot a^2, a^8 = a^4 \cdot a^4, \dots$ を計算し、これらを適切に掛け合わせることで、合計 $O(\log n)$ 回の乗算で $a^n$ が求まる。競技プログラミングにおいては行列などに対してもよく用いられる。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 繰り返し二乗法 21 | -------------------------------------------------------------------------------- /_algorithms/binary-search.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-23T00:00:00+09:00 8 | algorithm: 9 | input: 長さ $N$ のソート済みの列 $a$ と検索対象の要素 $b$ 10 | output: $b$ が含まれる位置 $i$。あるいは、$b$ を挿入してもソート済みのまま保たれるような区間 $\lbrack l, r)$ 11 | time_complexity: $O(\log N)$ など 12 | space_complexity: 13 | aliases: bisection 14 | level: green 15 | description: 二分探索とは、ソート済みの列に対する探索アルゴリズムのひとつ。探索すべき区間の中央の要素を調べることで探索すべき区間の長さを半々にし、区間の長さ $N$ に対し $O(\log N)$ で位置を特定する。 16 | draft: true 17 | draft_urls: ["https://twitter.com/meguru_comp/status/697008509376835584"] 18 | --- 19 | 20 | # 二分探索 21 | 22 | ## 話題 23 | 24 | - めぐる式 25 | - 浮動小数点数の場合 26 | - 標準ライブラリ内の関数 27 | - 二分法との違い 28 | - 現実での利用例: git bisect (開発) 29 | - 現実での利用例: LSB Decryption Oracle Attack (CTF) 30 | -------------------------------------------------------------------------------- /_algorithms/boruvka.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kort0n 6 | reviewers: kimiyuki 7 | date: 2021-03-01T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: orange 15 | description: Borůvka 法とは、最小全域木を求めるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Borůvka 法 21 | -------------------------------------------------------------------------------- /_algorithms/boyer-moore-horspool.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: パターン文字列 $P$ とテキスト文字列 $T$ 10 | output: パターン文字列 $P$ がテキスト文字列 $T$ に含まれるかどうか。含まれるならその位置も求める。 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: black 15 | description: Boyer-Moore-Horspool 法は、文字列検索アルゴリズムのひとつ。Boyer-Moore 法を簡略化したものである。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Boyer-Moore-Horspool 法 21 | 22 | ## 概要 23 | 24 | Boyer-Moore-Horspool 法は、文字列検索アルゴリズムのひとつ。Boyer-Moore 法を簡略化したものである。 25 | 26 | ## 詳細 27 | 28 | (省略) 29 | 30 | 31 | ## 関連項目 32 | 33 | - [Boyer-Moore 法](/algorithm-encyclopedia/boyer-moore) 34 | - Boyer-Moore-Horspool 法は Boyer-Moore 法を簡略化したアルゴリズムである。 35 | 36 | ## 外部リンク 37 | 38 | - [boyer_moore_horspool_searcher - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/functional/boyer_moore_horspool_searcher.html)[archive.org](https://web.archive.org/web/20210125045405/https://cpprefjp.github.io/reference/functional/boyer_moore_horspool_searcher.html) 39 | - C++ の標準ライブラリには Boyer-Moore-Horspool 法を用いた関数オブジェクトが `std::boyer_moore_horspool_searcher` として含まれている。 40 | -------------------------------------------------------------------------------- /_algorithms/boyer-moore-majority-vote-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: noshi91 6 | reviewers: ["MiSawa", "uwi"] 7 | date: 2021-06-09T14:03:49+09:00 8 | algorithm: 9 | input: 長さ $N$ の列 $a$ 10 | output: $a$ に $\frac{N}{2}$ 回を超えて出現する要素が存在するかどうか、存在する場合その要素 11 | time_complexity: $\Theta(N)$ 12 | space_complexity: $\Theta(1)$ 13 | aliases: [] 14 | level: yellow 15 | description: > 16 | Boyer-Moore majority vote algorithm は、列の過半数を占める要素を効率的に発見するアルゴリズムの一つである。 17 | 相異なる要素を繰り返し対にして、対にならずに残った要素が過半数となる候補であるという事実を用いる。 18 | 要素に対しては一致判定のみを用いるため、全順序などが定義されている必要が無い。 19 | 過半数を占める要素が存在しない場合何を出力しても良いことにすると、計算量をそのままに、列を一度走査するだけで計算することが可能になる。 20 | --- 21 | 22 | # Boyer-Moore majority vote algorithm 23 | 24 | ## 概要 25 | 26 | Boyer-Moore majority vote algorithm は、列の過半数を占める要素を効率的に発見するアルゴリズムの一つである。 27 | 相異なる要素を繰り返し対にして、対にならずに残った要素が過半数となる候補であるという事実を用いる。 28 | 要素に対しては一致判定のみを用いるため、全順序などが定義されている必要が無い。 29 | 過半数を占める要素が存在しない場合何を出力しても良いことにすると、計算量をそのままに、列を一度走査するだけで計算することが可能になる。 30 | 31 | ## 詳細 32 | 33 | $a$ から相異なる $2$ 要素を対にして、それらを取り除くことを操作が不可能になるまで繰り返すことを考える。 34 | このとき、$a$ に残る要素が存在するならば全て等しくなっており、この要素のみが $a$ の過半数を占める可能性がある。 35 | 36 | #### 証明 37 | 38 | $x$ が $a$ に $\frac{N}{2}$ 回を超えて出現するとする。 39 | 対を作るたびに $x$ は高々 $1$ つずつ $a$ から取り除かれるが、対は $\frac{N}{2}$ 個以下しか作れないため、$x$ は最後まで完全に取り除かれることが無い。 40 | $\blacksquare$ 41 | 42 | アルゴリズムにおいては、$a$ を前から順に参照して、相異なる $2$ 要素を発見したら直ちに取り除く。 43 | より正確には $i = 0, 1, \dots, N - 1$ の順に、$a _ j$ が取り除かれていないかつ $a _ j \neq a _ i, j \lt i$ となるような $j$ が存在するならば $a _ j$ と $a _ i$ を取り除く、という操作を繰り返す。 44 | そのような $j$ の存在を効率的に判定するために、多重集合 $S \coloneqq \lbrace a _ j \mid j \lt i, a _ j$ は取り除かれていない $\rbrace$ を管理する。 45 | $S$ は空であるか、あるいは $1$ 種類の要素だけから構成されているため、$1$ つの元と $\lvert S \rvert$ だけを管理すればよい。 46 | この表現によって、$a _ j$ の発見や $S$ の更新は全て時間計算量 $\Theta(1)$ で実行される。 47 | 48 | これによって得られた出力の候補が実際に過半数を占めるかどうかは、もう一度 $a$ を走査することで確認できる。 49 | 50 | 空間計算量は $a$ の元を $\mathrm{O}(1)$ で保持できると仮定すると $\Theta(\log(N))$ bits となる。 51 | これは $\lvert S \rvert$ の保持や、最後の確認で数えるときに $N$ 以下の整数を持つ必要があるためである。 52 | Word-RAM を仮定すれば $\Theta(1)$ となる。 53 | 54 | ## 一般化 55 | 56 | 長さ $N$ の列 $a$ と $1 \leq k \leq N$ を満たす整数 $k$ が与えられたとき、$a$ に $\frac{N}{k + 1}$ 回を超えて出現する要素を列挙することが $\Theta(Nk)$ の時間計算量、$\Theta(k)$ の空間計算量で可能である。 57 | 元のアルゴリズムとほとんど同様に、$k + 1$ 個の互いに相異なる要素を組にして、組になっていない高々 $k$ 種類の要素とそれぞれの個数を管理すればよい。 58 | $k = 1$ の場合が Boyer-Moore majority vote algorithm である。 59 | 60 | ## その他 61 | 62 | - 同様の考え方で、Segment Tree を用いて、区間の過半数を占める要素の候補を発見できる。 63 | それぞれのノードは対応する区間で対にならずに残る要素とその個数を管理し、区間をマージする際は必要なだけ対を作れば、常に $1$ 種類以下の要素が残る状態が保たれる。 64 | 発見した要素が本当に過半数を占めるかどうかを確認する必要がある場合、別途データ構造が必要となる。 65 | 例えば、各値について平衡二分探索木を管理する方法が挙げられる。 66 | 67 | ## 参考文献 68 | 69 | - Boyer, R. S., & Moore, J. S. (1991). MJRTY—a fast majority vote algorithm. In Automated Reasoning (pp. 105-117). Springer, Dordrecht. 70 | - Boyer-Moore majority vote algorithm が提案された論文 71 | -------------------------------------------------------------------------------- /_algorithms/boyer-moore.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: パターン文字列 $P$ とテキスト文字列 $T$ 10 | output: パターン文字列 $P$ がテキスト文字列 $T$ に含まれるかどうか。含まれるならその位置も求める。 11 | time_complexity: 前処理は $O(\vert P \vert)$ である。検索は、ランダムな文字列に対しては $O(\vert T \vert / \vert P \vert)$ だが最悪ケースは $O(\vert P \vert \cdot \vert T \vert)$ である。 12 | space_complexity: 13 | aliases: ["BM法"] 14 | level: orange 15 | description: Boyer-Moore 法とは、文字列検索アルゴリズムのひとつ。どこで不一致が起きたらパターン文字列をいくつずらせばよいかの情報を $O(\vert P \vert)$ かけて構築しておき、パターン文字列をその末尾から順にテキスト文字列と照合していく。ランダムな文字列に対しては $O(\vert T \vert / \vert P \vert)$ だが、最悪ケースでは $O(\vert P \vert \cdot \vert T \vert)$ かかる。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Boyer-Moore 法 21 | 22 | ## 概要 23 | 24 | Boyer-Moore 法とは、文字列検索アルゴリズムのひとつ。どこで不一致が起きたらパターン文字列をいくつずらせばよいかの情報を $O(\vert P \vert)$ かけて構築しておき、パターン文字列をその末尾から順にテキスト文字列と照合していく。ランダムな文字列に対しては $O(\vert T \vert / \vert P \vert)$ だが、最悪ケースでは $O(\vert P \vert \cdot \vert T \vert)$ かかる。 25 | 26 | ## 詳細 27 | 28 | (省略) 29 | 30 | ## 参考文献 31 | 32 | - Robert S. Boyer and J. Strother Moore. 1977. A fast string searching algorithm. Commun. ACM 20, 10 (Oct. 1977), 762–772. DOI: 33 | - Boyer-Moore 法が提案された論文 34 | 35 | ## 関連項目 36 | 37 | - [Boyer-Moore-Horspool 法](/algorithm-encyclopedia/boyer-moore-horspool) 38 | - Boyer-Moore-Horspool 法は Boyer-Moore 法を簡略化したアルゴリズムである。 39 | - [Knuth-Morris-Pratt 法](/algorithm-encyclopedia/knuth-morris-pratt) 40 | - Knuth-Morris-Pratt 法は Boyer-Moore 法と並んで競技プログラミングでよく用いられる単一パターン文字列検索アルゴリズムである。 41 | 42 | ## 外部リンク 43 | 44 | - [boyer_moore_searcher - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/functional/boyer_moore_searcher.html)[archive.org](https://web.archive.org/web/20210225123633/https://cpprefjp.github.io/reference/functional/boyer_moore_searcher.html) 45 | - C++ の標準ライブラリには Boyer-Moore 法を用いた関数オブジェクトが `std::boyer_moore_searcher` として含まれている。 46 | -------------------------------------------------------------------------------- /_algorithms/centroid-decomposition.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: "centroid decomposition" 14 | level: blue 15 | description: 重心分解とは、木を分解する手法のひとつである。木からその重心を削除することを再帰的に行う。重心の削除のたびに木の大きさが半分以下になる。分解の過程に沿って重心だった頂点の集合に木構造を入れたとき、元々の木の頂点数を $n$ とすると分解されてできた木の高さが $O(\log n)$ になることを特徴とする。 16 | draft: true 17 | draft_urls: "https://qiita.com/drken/items/4b4c3f1824339b090202" 18 | --- 19 | 20 | # 重心分解 21 | -------------------------------------------------------------------------------- /_algorithms/chinese-remainder-theorem.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: ["MiSawa", "hos_lyric"] 7 | date: 2021-02-28T00:00:00+09:00 8 | tags: algorithm 9 | algorithm: 10 | input: 11 | output: 12 | time_complexity: 13 | space_complexity: 14 | aliases: ["Chinese remainder theorem", "CRT", "中国人剰余定理"] 15 | level: blue 16 | description: | 17 | 中国剰余定理とは、任意の互いに素な正整数 $m, n$ に対して、剰余環 $\mathbb{Z}/m n \mathbb{Z}$ と剰余環の直積環 $(\mathbb{Z}/m \mathbb{Z}) \times (\mathbb{Z}/n \mathbb{Z})$ とが $\phi(x) = (x \bmod m, x \bmod n)$ で定まる写像 $\phi : \mathbb{Z}/m n \mathbb{Z} \to (\mathbb{Z}/m \mathbb{Z}) \times (\mathbb{Z}/n \mathbb{Z})$ によって環同型である、という定理のこと。あるいは同じことだが、任意の互いに素な正整数 $m, n$ および任意の整数 $a, b$ に対して、ある整数 $x$ が $m n$ を法として一意に存在して、$x \equiv a \pmod{m}$ かつ $x \equiv b \pmod{n}$ を満たす、という定理のこと。 18 | draft: true 19 | draft_urls: ["http://elliptic-shiho.hatenablog.com/entry/2016/04/03/020117", "https://qiita.com/drken/items/ae02240cd1f8edfc86fd"] 20 | --- 21 | 22 | # 中国剰余定理 23 | -------------------------------------------------------------------------------- /_algorithms/chirp-z-transform.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: noshi91 6 | reviewers: ["kimiyuki"] 7 | date: 2021-09-15T21:46:53+09:00 8 | algorithm: 9 | input: 体 $\mathbb{K}$ 上の長さ $n$ の列 $x$、$a \in \mathbb{K}, w \in \mathbb{K}$、整数 $m$ 10 | output: 各 $0 \leq k \lt m$ に対し、$X _ {k} = \sum _ {i = 0} ^ {n - 1} x _ {i} (a ^ {- 1} w ^ {k}) ^ {i}$ 11 | time_complexity: $\mathrm{M}(n, n + m - 1) + \Theta(n + m)$ 12 | space_complexity: $\mathrm{M}(n, n + m - 1) + \Theta(n + m)$ 13 | aliases: ["Bluestein's algorithm", "chirp transform", "CZT"] 14 | level: red 15 | description: > 16 | chirp z-transform は、有限列の z-transform を等比数列を成す点で評価した値を計算するアルゴリズムの一つ。 17 | 長さが $2$ の冪でない離散フーリエ変換の計算などに使用できる。 18 | 時間計算量/空間計算量は、$\mathrm{M}(M, N)$ を長さ $M, N$ の列の畳み込みに必要な計算量として、$\mathrm{M}(n, n + m - 1) + \Theta(n + m)$ である。 19 | --- 20 | 21 | # chirp z-transform 22 | 23 | ## 概要 24 | 25 | chirp z-transform は、有限列の Z 変換を等比数列を成す点で評価した値を計算するアルゴリズムの一つ。 26 | 長さが $2$ の冪でない離散フーリエ変換の計算などに使用できる。 27 | 時間計算量/空間計算量は、$\mathrm{M}(M, N)$ を長さ $M, N$ の列の畳み込みに必要な計算量として、$\mathrm{M}(n, n + m - 1) + \Theta(n + m)$ である。 28 | 29 | $a$ が $- 1$ 乗されているのは Z 変換に由来するもので、取り除けば多項式の多点評価と解釈できる ($a ^ {- 1}$ を $a$ と定義し直せば相互に変換可能である)。 30 | 31 | ## 詳細 32 | 33 | $w = 0$ の場合は自明であるから、以降 $w \neq 0$ とする。 34 | 35 | 三角数を $t _ {i} \coloneqq \frac{i(i - 1)}{2}$ と書くことにすると、以下の等式が成り立つ。 36 | $$ 37 | ki = t _ {k + i} - t _ {k} - t _ {i} 38 | $$ 39 | 40 | これを用いて $X _ {k}$ を変形すると以下のようになる。 41 | $$ \begin{align*} 42 | X _ {k} 43 | &= \sum _ {i = 0} ^ {n - 1} x _ {i} (a ^ {- 1} w ^ {k}) ^ {i} \cr 44 | &= \sum _ {i = 0} ^ {n - 1} x _ {i} a ^ {- i} w ^ {ki} \cr 45 | &= \sum _ {i = 0} ^ {n - 1} x _ {i} a ^ {- i} w ^ {t _ {k + i}} w ^ {- t _ {k}} w ^ {- t _ {i}} \cr 46 | &= w ^ {- t _ {k}} \sum _ {i = 0} ^ {n - 1} (x _ {i} a ^ {- i} w ^ {- t _ {i}}) w ^ {t _ {k + i}} 47 | \end{align*} $$ 48 | 最後の式は畳み込みの形になっている。 49 | 実際、長さ $n$ の列 $y$ と長さ $n + m - 1$ の列 $v$ を 50 | $$ \begin{aligned} 51 | y _ {i} &\coloneqq x _ {i} a ^ {- i} w ^ {- t _ {i}} \cr 52 | v _ {i} &\coloneqq w ^ {t _ {i}} 53 | \end{aligned} $$ 54 | と定義すれば 55 | $$ \begin{align*} 56 | X _ {k} 57 | &= w ^ {- t _ {k}} \sum _ {i = 0} ^ {n - 1} y _ {i} v _ {k + i} \cr 58 | &= w ^ {- t _ {k}} \sum _ {i + j = n - 1 + k} y _ {n - 1 - i} v _ {j} 59 | \end{align*} $$ 60 | となる。 61 | 62 | 関係式 $w ^ {t _ {i + 1}} = w ^ {t _ {i}} w ^ {i}$ を用いることで $y, v$ は $\Theta(n + m)$ で計算できる。 63 | よって全体の計算量は、これに畳み込みに掛かる時間計算量を加えた $\mathrm{M}(n, n + m - 1) + \Theta(n + m)$ となる。 64 | 65 | 畳み込みの結果のうち第 $n - 1$ 項から第 $n + m - 2$ 項までを使用するため、畳み込みは長さ $n + m - 1$ 以上の巡回畳み込みでも問題ない。 66 | $\mathbb{K} = \mathbb{C}$ や $\mathbb{K} = \mathbb{F} _ {p}$ の場合は離散フーリエ変換を用いた巡回畳み込みが効率的に行えるため、定数倍高速化が見込める。 67 | 68 | ## その他 69 | 70 | - $y \in \mathbb{K} ^ {n}$ を固定して写像 $f _ {y} \colon \mathbb{K} ^ {n + m - 1} \to \mathbb{K} ^ {m}$ を $f _ {y}(v) _ {k} = \sum _ {i = 0} ^ {n - 1} y _ {i} v _ {k + i}$ によって定めると $X _ {k} = w ^ {- t _ {k}} f _ {y}(v) _ {k}$ であるから、$f _ {y}$ の高速な計算が問題となる。 71 | $f _ {y}$ は線形写像となるが、これを行列で表現し転置して得られる写像 $g _ {y} \colon \mathbb{K} ^ {m} \to \mathbb{K} ^ {n + m - 1}$ は引数と $y$ の畳み込みに一致する。 72 | Tellegen's principle により、線形写像を計算するアルゴリズムが特定の条件を満たす時、その転置写像もまた同じ計算量で計算できることが知られている。 73 | 従って畳み込みのアルゴリズムが特定の条件を満たすならば、$f _ {y}$ はその転置 $g _ {y}$ と同じ計算量 $\mathrm{M}(n, m)$ で計算できる。 74 | 実際、本ページ中で示した離散フーリエ変換を用いる場合の定数倍高速化も Tellegen's principle から導出できる。 75 | 76 | ## 参考文献 77 | 78 | 1. Rabiner, L., Schafer, R. W., & Rader, C. (1969). The chirp z-transform algorithm. IEEE transactions on audio and electroacoustics, 17(2), 86-92. 79 | - chirp z-transform が提案された論文 80 | 1. Crandall, R., & Pomerance, C. B. (2006). Prime numbers: a computational perspective (Vol. 182). Springer Science & Business Media. 81 | - 参考文献 1 のアルゴリズムにおいて三角数を用いて $w ^ {1 / 2}$ の計算を不要にする方法が説明されている 82 | 1. Bostan, A., & Schost, É. (2005). Polynomial evaluation and interpolation on special sets of points. Journal of Complexity, 21(4), 420-446. 83 | - 参考文献 2 のアルゴリズムにおいて三角数の使い方を少しだけ変えている。 84 | 本ページはこのアルゴリズムを説明している。 85 | 1. Bostan, A., Lecerf, G., & Schost, É. (2003, August). Tellegen's principle into practice. In Proceedings of the 2003 international symposium on Symbolic and algebraic computation (pp. 37-44). 86 | - 離散フーリエ変換を用いた畳み込みを転置するアルゴリズムの導出についての記述がある 87 | -------------------------------------------------------------------------------- /_algorithms/chokudai-search.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-02-28T00:00:00+09:00 8 | tags: algorithm 9 | algorithm: 10 | input: 11 | output: 12 | time_complexity: 13 | space_complexity: 14 | aliases: 15 | level: orange 16 | description: chokudai サーチはグラフ探索アルゴリズムのひとつである。ビームサーチを変形したもので、それ以前の実行ですでに探索した頂点を無視しながら、保持する頂点数 $K$ が小さいビームサーチを繰り返し実行する。これには、定数 $K$ の調整を省略する効果と、似通った頂点ばかりを探索することを防ぐ効果がある。 17 | draft: true 18 | draft_urls: ["http://chokudai.hatenablog.com/entry/2017/04/12/055515"] 19 | --- 20 | 21 | # chokudai サーチ 22 | -------------------------------------------------------------------------------- /_algorithms/chu-liu-edmonds.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: minaminao 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺重み $c : V \to \mathbb{R}$ 付き有向グラフ $G = (V, E)$ および頂点 $r \in V$ 11 | output: $r$ を根とする最小全域有向木 $T$ 12 | time_complexity: $O(V E)$ 13 | space_complexity: 14 | aliases: 15 | level: black 16 | description: Chu-Liu/Edmonds' algorithm とは、与えられた辺重み付き有向グラフ $G$ と頂点 $r$ に対し、$r$ を根とする最小全域有向木を $O(V E)$ で求めるアルゴリズムである。 17 | draft: true 18 | draft_urls: "https://ark4rk.hatenablog.com/entry/2017/09/15/011937" 19 | --- 20 | 21 | # Chu-Liu/Edmonds' algorithm 22 | -------------------------------------------------------------------------------- /_algorithms/coordinate-compression.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 長さ $N$ の整数列 $a$ 10 | output: | 11 | 長さ $N$ の自然数列 $b$ であって、要素の順序関係が $a$ と同じでかつ最大値 $\max_i b_i$ が最小であるもの 12 | time_complexity: $O(N \log N)$ 13 | space_complexity: 14 | aliases: ["座圧"] 15 | level: cyan 16 | description: | 17 | 座標圧縮とは、与えられた長さ $N$ の整数列 $a$ から、長さ $N$ の自然数列 $b$ であって要素の順序関係が $a$ と同じでかつ最大値 $\max_i b_i$ が最小であるような $b$ を作ること。ただし「要素の順序関係が同じ」とは、任意の $i, j$ に対し $a_i \le a_j \leftrightarrow b_i \le b_j$ を満たすことを言う。このような $b$ は常に一意に存在し、単純な方法により $O(N \log N)$ で構成できる。 18 | draft: true 19 | draft_urls: [] 20 | --- 21 | 22 | # 座標圧縮 23 | -------------------------------------------------------------------------------- /_algorithms/cumulative-sum.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 長さ $N$ の数列 $a$ 10 | output: 長さ $N + 1$ の数列 $b$ (ただし $b_i = \sum _ {j \lt i} a_i$) 11 | time_complexity: 構築に $O(N)$ で利用に $O(1)$ 12 | space_complexity: $O(N)$ 13 | aliases: [] 14 | level: green 15 | description: 累積和とは、ある数列の接頭辞の総和たちを要素とする数列のこと。長さ $N$ の数列 $a = (a_0, a_1, \dots, a _ {N - 1})$ に対する累積和とは $b_i = \sum _ {j \lt i} a_i$ であるような長さ $N + 1$ の数列 $b$ である。数列の要素が群の要素であるときには区間 $\lbrack l, r)$ の総和 $\sum _ {i \in \lbrack l, r)} a_i = b_r - b_l$ を $O(1)$ で計算することなどに用いることができる。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 累積和 21 | 22 | ## 話題 23 | 24 | - imos 法との関連 25 | - 可換性についての注意 26 | - 標準ライブラリ内の関数 `std::partial_sum` 27 | - 現実での利用例: 疎行列 28 | -------------------------------------------------------------------------------- /_algorithms/d-edge-shortest-path-monge.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: ページ作成 5 | authors: noshi91 6 | reviewers: ["kimiyuki", "MiSawa"] 7 | date: 2021-04-03T10:30:00+09:00 8 | algorithm: 9 | input: > 10 | Monge 性を満たす整数の辺重み $c : E \to \mathbb{Z}$ 付き完全 DAG $G = (N, E = \lbrace (i, j) \mid i \lt j \rbrace)$ 及び正整数 $d$ 11 | output: 辺を丁度 $d$ 本使う条件下での $0$-$(N - 1)$ 最短路長 12 | time_complexity: $\Theta (N \log(\max _ {e \in E} \lvert c(e) \rvert))$ 13 | space_complexity: $\Theta (N)$ 14 | aliases: ["Alien DP", "WQS binary search"] 15 | level: orange 16 | description: > 17 | 辺の重みが Monge 性を満たすような完全 DAG について、辺を丁度 $d$ 本使う条件下での $0$-$(N - 1)$ 最短路長を $\Theta (N \log(\max _ {e \in E} \lvert c(e) \rvert))$ で計算する。 18 | ラグランジュ双対問題との強双対性が $c$ の Monge 性から成り立ち、ラグランジュ緩和問題もまた Monge 性を利用して高速に解くことができる。 19 | --- 20 | 21 | # Monge グラフ上の $d$-辺最短路長を計算するアルゴリズム 22 | 23 | ## 概要 24 | 25 | $G = (N, E = \lbrace (i, j) \mid i \lt j \rbrace)$ を $N$ 頂点の完全 DAG、$c : E \to \mathbb{Z}$ を Monge 性を満たす辺重み、$d$ を正整数とする。 26 | 辺を丁度 $d$ 本使う条件下での $0$-$(N - 1)$ 最短路長を計算する問題を考える。 27 | 28 | この問題は制約付き最適化であり、そのラグランジュ双対問題との強双対性が $c$ の Monge 性から成り立つ。 29 | この強双対性を利用することで、ラグランジュ緩和問題を $\Theta(\log (\max _ {e \in E} \lvert c(e) \rvert))$ 回解く問題に帰着することができる。 30 | 31 | ラグランジュ緩和問題は、全ての辺の重みを $\lambda$ 大きくした場合の (辺の数の制約のない) 最短路問題となる。 32 | $c$ が Monge なら、一様に $\lambda$ を加算したものもまた Monge である。 33 | Monge 性を満たす辺重みについての最短路は LARSCH Algorithm[^LARSCH] を用いて $\Theta (N)$ で計算することができる。 34 | 35 | 従って、元の問題である Monge グラフ上の $d$-辺最短路長は $\Theta(N \log (\max _ {e \in E} \lvert c(e) \rvert))$ で計算できる。 36 | 37 | Aliens[^Aliens] はこの問題に帰着することができる。 38 | それに由来して、特にラグランジュ緩和問題を用いる発想を指して Alien DP と呼ぶことがある[^kort0n-AlienDP]。 39 | また、WQS binary search とも呼ばれる[^WQS-binary-search]。 40 | 41 | ## Monge 42 | 43 | この記事中では、辺重み $c : E \to \mathbb{Z}$ が Monge であるとは、 44 | $$\forall i, j, k, l.\ 0 \leq i \lt j \lt k \lt l \lt N \rightarrow c(i, l) + c(j, k) \geq c(i, k) + c(j, l)$$ 45 | を満たすことを言うこととする。 46 | 47 | Monge は通常は $M \times N$ 行列に対して定義される概念であるが、ここでは $c$ が上三角部分のみについて定義されているので、制限した形で定義した。 48 | 49 | ## ラグランジュ双対問題 50 | 51 | $\mathcal{P}$ を $G$ の $0$-$(N - 1)$ パス全体とする。 52 | $P \in \mathcal{P}$ に対して、$\lVert P \rVert$ を $P$ の辺の本数、$c(P)$ を $P$ の辺の重みの和とする。 53 | 54 | 求めたい値は $\displaystyle \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P)$ である。 55 | 56 | 任意の $\lambda \in \mathbb{Z}$ に対して、以下の式が成り立つ。 57 | $$ \begin{equation} \begin{aligned} 58 | \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P) & = \min _ {P \in \mathcal{P}, \lVert P \rVert = d} (c(P) + \lambda (\lVert P \rVert - d)) \cr 59 | & \geq \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d)) 60 | \end{aligned} \end{equation}$$ 61 | このように制約の一部を除去し、除去した制約について違反した量を一次のペナルティ[^lagrangian-penalty] として目的関数に組み込んだ問題をラグランジュ緩和問題と呼ぶ[^lagrangian-relaxation]。 62 | ラグランジュ緩和問題の解は、元の問題の解の下界を与えている。 63 | 64 | $(1)$ から、さらに以下の式が成り立つ。 65 | $$ \begin{equation} 66 | \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P) \geq \max _ {\lambda \in \mathbb{Z}} \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d)) 67 | \end{equation} $$ 68 | これは、$\lambda$ を調整することで得られる最もよい下界を考えていると解釈できる。 69 | この最良の下界を求める問題をラグランジュ双対問題と呼ぶ。 70 | 71 | $(2)$ において、一般には等号が成立するとは限らないが、この問題の設定では等号が成立する。 72 | 主問題と双対問題の解が一致することを、強双対性と呼ぶ。 73 | 以降の補題の主な目的は強双対性 (定理 $3$) を示すことである。 74 | 75 | $P _ k ^ {\ast}$ を、丁度 $k$ 本の辺を使う条件下の $0$-$(N-1)$ 最短路と定義する。 76 | 複数存在する場合、任意に $1$ つとる。 77 | 78 | ### 補題 $1$ 79 | 80 | $$\forall k.\ 2 \leq k \leq N - 2 \rightarrow c(P _ k ^ {\ast}) - c(P _ {k - 1} ^ {\ast}) \leq c(P _ {k + 1} ^ {\ast}) - c(P _ k ^ {\ast})$$ 81 | 82 | #### 証明 83 | 84 | $\lVert P \rVert = \lVert P ^ {\prime} \rVert = k$ を満たすパス $P, P ^ {\prime} \in \mathcal{P}$ であって $c(P _ {k - 1} ^ {\ast}) + c(P _ {k + 1} ^ {\ast}) \geq c(P) + c(P ^ {\prime})$ であるものの存在を示す。 85 | もしそれが示されたならば、$c(P _ {k - 1} ^ {\ast}) + c(P _ {k + 1} ^ {\ast}) \geq c(P) + c(P ^ {\prime}) \geq c(P _ k ^ {\ast}) + c(P _ k ^ {\ast})$ を移項することで求める式を得る。 86 | 87 | パスを頂点の列として表現する。 88 | $P _ {k - 1} ^ {\ast} = (s _ 0, s _ 1, \dots, s _ {k - 1}), P _ {k + 1} ^ {\ast} = (t _ 0, t _ 1, \dots, t _ {k + 1})$ とする。 89 | $s _ 0 = t _ 0 = 0, s _ {k - 1} = t _ {k + 1} = N - 1$ である。 90 | 各 $0 \leq x \leq k - 1$ について、$s _ x$ と $t _ {x + 1}$ の大小を比較する。 91 | $s _ 0 \lt t _ 1$ かつ $s _ {k - 1} \gt t _ k$ であるから、$s _ x = t _ {x + 1}$ を満たす $x$ が存在するか、さもなくば $s _ x \lt t _ {x + 1} \land s _ {x + 1} \gt t _ {x + 2}$ を満たす $x$ が存在する。 92 | 93 | - $s _ x = t _ {x + 1}$ を満たす $x$ が存在する場合 94 | 95 | $$ \begin{align*} 96 | P &\coloneqq (s _ 0, s _ 1, \dots, s _ x, t _ {x + 2}, t _ {x + 3}, \dots, t _ {k + 1}) \cr 97 | P ^ {\prime} &\coloneqq (t _ 0, t _ 1, \dots, t _ {x + 1}, s _ {x + 1}, s _ {x + 2}, \dots, s _ {k - 1}) 98 | \end{align*} $$ 99 | とすればよい。 100 | $c(P _ {k - 1} ^ {\ast}) + c(P _ {k + 1} ^ {\ast}) = c(P) + c(P ^ {\prime})$ である。 101 | - $s _ x \lt t _ {x + 1} \land s _ {x + 1} \gt t _ {x + 2}$ を満たす $x$ が存在する場合 102 | 103 | 整理すると、$s _ x \lt t _ {x + 1} \lt t _ {x + 2} \lt s _ {x + 1}$ である。 104 | $$ \begin{align*} 105 | P &\coloneqq (s _ 0, s _ 1, \dots, s _ x, t _ {x + 2}, t _ {x + 3}, \dots, t _ {k + 1}) \cr 106 | P ^ {\prime} &\coloneqq (t _ 0, t _ 1, \dots, t _ {x + 1}, s _ {x + 1}, s _ {x + 2}, \dots, s _ {k - 1}) 107 | \end{align*} $$ 108 | とすればよい。 109 | $c$ の Monge 性から $c(s _ x, s _ {x + 1}) + c(t _ {x + 1}, t _ {x + 2}) \geq c(s _ x, t _ {x + 2}) + c(t _ {x + 1}, s _ {x + 1})$ であり、$c(P _ {k - 1} ^ {\ast}) + c(P _ {k + 1} ^ {\ast}) \geq c(P) + c(P ^ {\prime})$ が従う。 110 | 111 | $\blacksquare$ 112 | 113 | 補題 $1$ は $k \mapsto c(P _ k ^ {\ast})$ が下に凸であることを意味している。 114 | 115 | ### 補題 $2$ 116 | 117 | $\displaystyle \lVert P ^ {\ast} \rVert = d \land P ^ {\ast} \in \argmin _ {P \in \mathcal{P}} (c(P) + \lambda ^ {\ast} (\lVert P \rVert - d))$ を満たす $\lambda ^ {\ast} \in \mathbb{Z}, P ^ {\ast} \in \mathcal{P}$ が存在する。 118 | 119 | #### 証明 120 | 121 | 補題 $1$ を用いて、$- (c(P _ {d + 1} ^ {\ast}) - c(P _ d ^ {\ast})) \leq \lambda ^ {\ast} \leq - (c(P _ d ^ {\ast}) - c(P _ {d - 1} ^ {\ast}))$ を満たすように $\lambda ^ {\ast}$ をとる。 122 | $\forall k.\ c (P _ k ^ {\ast}) + \lambda ^ {\ast} (k - d) \geq c (P _ d ^ {\ast})$ を示せば、$\displaystyle P _ d ^ {\ast} \in \argmin _ {P \in \mathcal{P}} (c(P) + \lambda ^ {\ast} (\lVert P \rVert - d))$ であるから、$P ^ {\ast}$ として $P _ d ^ {\ast}$ をとることができる。 123 | 124 | - $k \lt d$ の場合 125 | 126 | $$ \begin{aligned} 127 | c (P _ k ^ {\ast}) + \lambda ^ {\ast} (k - d) 128 | & = c(P _ d ^ {\ast}) - \sum _ {i = k} ^ {d - 1} (c(P _ {i + 1} ^ {\ast}) - c(P _ i ^ {\ast})) + \lambda ^ {\ast} (k - d) \cr 129 | & \geq c(P _ d ^ {\ast}) - (c(P _ d ^ {\ast}) - c(P _ {d - 1} ^ {\ast})) (d - k) + \lambda ^ {\ast} (k - d) & & (\because \text{補題}\ 1) \cr 130 | & \geq c(P _ d ^ {\ast}) + \lambda ^ {\ast} (d - k) + \lambda ^ {\ast} (k - d) & & (\because \lambda ^ {\ast} \text{の定義}) \cr 131 | & = c (P _ d ^ {\ast}) 132 | \end{aligned} $$ 133 | - $k \geq d$ の場合 134 | 135 | $$ \begin{aligned} 136 | c(P _ k ^ {\ast}) + \lambda ^ {\ast} (k - d) 137 | & = c(P _ d ^ {\ast}) + \sum _ {i = d} ^ {k - 1} (c(P _ {i + 1} ^ {\ast}) - c(P _ i ^ {\ast})) + \lambda ^ {\ast} (k - d) \cr 138 | & \geq c(P _ d ^ {\ast}) + (c(P _ {d + 1} ^ {\ast}) - c(P _ d ^ {\ast})) (k - d) + \lambda ^ {\ast} (k - d) & & (\because \text{補題}\ 1) \cr 139 | & \geq c(P _ d ^ {\ast}) - \lambda ^ {\ast}(k - d) + \lambda ^ {\ast} (k - d) & & (\because \lambda ^ {\ast} \text{の定義}) \cr 140 | & = c (P _ d ^ {\ast}) 141 | \end{aligned} $$ 142 | 143 | $\blacksquare$ 144 | 145 | ### 定理 $3$ 146 | 147 | $$ 148 | \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P) = \max _ {\lambda \in \mathbb{Z}} \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d)) 149 | $$ 150 | 151 | #### 証明 152 | 153 | 補題 $2$ を用いて、$\displaystyle \lVert P ^ {\ast} \rVert = d \land P ^ {\ast} \in \argmin _ {P \in \mathcal{P}} (c(P) + \lambda ^ {\ast} (\lVert P \rVert - d))$ を満たす $\lambda ^ {\ast}, P ^ {\ast}$ をとる。 154 | 155 | $$ \begin{aligned} 156 | \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P) & \leq c(P ^ {\ast}) \cr 157 | & = c(P ^ {\ast}) + \lambda ^ {\ast} (\lVert P ^ {\ast} \rVert - d) \cr 158 | & = \min _ {P \in \mathcal{P}} (c(P) + \lambda ^ {\ast}(\lVert P \rVert - d)) \cr 159 | & \leq \max _ {\lambda \in \mathbb{Z}} \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d)) 160 | \end{aligned} $$ 161 | 162 | $(2)$ と合わせることで求める式が示される。 163 | $\blacksquare$ 164 | 165 | ## アルゴリズム 166 | 167 | ラグランジュ双対問題 $\displaystyle \max _ {\lambda \in \mathbb{Z}} \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d))$ を解く。 168 | $\displaystyle L: \lambda \mapsto \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d))$ は $1$ 次関数群の $\min$ であるから、上に凸である。 169 | したがって、$L$ の最大値は三分探索を用いて計算することができる。 170 | 定理 $3$ より、得られた $L$ の最大値が、求める出力 $\displaystyle \min _ {P \in \mathcal{P}, \lVert P \rVert = d} c(P)$ である。 171 | 172 | 残る問題は $\lambda$ が与えられたとき $L(\lambda)$ を計算することである。 173 | 辺重み $c _ {\lambda} : E \to \mathbb{Z}$ を $c _ {\lambda} (e) = c(e) + \lambda$ によって定義する。 174 | すなわち、$c _ {\lambda}$ は全ての辺の重みを $c$ と比べて $\lambda$ 大きくした重みである。 175 | すると、以下のように変形できる。 176 | $$ \begin{aligned} 177 | L (\lambda) 178 | & = \min _ {P \in \mathcal{P}} (c(P) + \lambda (\lVert P \rVert - d)) \cr 179 | & = \min _ {P \in \mathcal{P}} (c (P) + \lambda \lVert P \rVert - \lambda d) \cr 180 | & = - \lambda d + \min _ {P \in \mathcal{P}} c _ {\lambda} (P) 181 | \end{aligned} $$ 182 | よって、$c _ {\lambda}$ についての最短路長を計算することで $L(\lambda)$ の値を得ることができる。 183 | 184 | $c$ が Monge であるから、$c _ {\lambda}$ もまた Monge である。 185 | 辺の重みが Monge 性を満たす完全 DAG の最短路の計算は LARSCH Algorithm[^LARSCH] を用いて $\Theta (N)$ で行うことができる。 186 | Aliens[^Aliens] では $c _ {\lambda}$ の性質が Monge よりさらに良く、Convex Hull Trick を用いることで同じく $\Theta (N)$ で最短路を計算することができる。 187 | 188 | $\lambda = - 3 \max _ {e \in E} \lvert c(e) \rvert$ とすると辺を $N - 1$ 本含むパスが最短となる。 189 | $\lambda$ をそれ以上小さくすると $L(\lambda)$ は単調減少するため、$- 3 \max _ {e \in E} \lvert c(e) \rvert$ は三分探索の下界として用いることができる。 190 | 同様に、$3 \max _ {e \in E} \lvert c(e) \rvert$ を上界に用いることができる。 191 | 192 | 193 | 時間計算量は全体で $\Theta (N \log (\max _ {e \in E} \lvert c(e) \rvert))$ となる。 194 | 195 | ## その他 196 | 197 | - $c(e)$ を全ての $e \in E$ について入力すると $\Theta(N ^ 2)$ となってしまうため、実際には $i, j$ を与えたときに $c(i, j)$ が $\Omicron(1)$ で計算できると仮定して、アルゴリズムの時間計算量を評価している。 198 | - $c _ {\lambda} (P)$ を最小化する $P$ についての $\lVert P \rVert$ が $\lambda$ について単調減少であることに着目し、丁度 $\lVert P \rVert = d$ となるような $\lambda$ を二分探索で求める[^exact] という方法も存在する。これは $L$ の最大化を傾きについての二部探索で行うことと概ね等価なアルゴリズムとなる。 199 | - $d$ 本以下の辺を使う条件下の最短路長も計算することができる。補題 $1$ より、$k \mapsto c(P _ k ^ {\ast})$ は下に凸である。したがって、$d$ 本以下の辺を使う条件下の最短路になり得るのは、条件なしでの最短路と $P _ d ^ {\ast}$ のみである。$d$ 本以上の辺を使う場合も同様に計算できる。 200 | 201 | ## 参考文献 202 | 203 | - Bein, W. W., Larmore, L. L., & Park, J. K. (1992). The d-edge shortest-path problem for a Monge graph (No. SAND-92-1724C; CONF-930194-1). Sandia National Labs., Albuquerque, NM (United States). 204 | 205 | - [岩田 陽一 (NII) (2018). 双対性. JOI春合宿.](https://www.slideshare.net/wata_orz/ss-91375739) [archive.org](https://web.archive.org/web/20201101134907/https://www.slideshare.net/wata_orz/ss-91375739) 206 | 207 | ## 注釈 208 | 209 | [^Aliens]: [IOI 2016 Aliens](https://ioinformatics.org/files/ioi2016problem6.pdf) [archive.org](https://web.archive.org/web/20191021104945/https://ioinformatics.org/files/ioi2016problem6.pdf) 210 | [^kort0n-AlienDP]: kort0n によるツイート [archive.org](https://web.archive.org/web/20200514195641/https://twitter.com/kyort0n/status/1260986271314227206) 211 | [^lagrangian-penalty]: $\lambda (\lVert P \rVert - d)$ は負にもなり得るため、ペナルティとしての解釈が難しい部分もある。厳密な議論は式変形を参照せよ。 212 | [^lagrangian-relaxation]: [ラグランジュ緩和問題 - 数理計画用語集](http://www.msi.co.jp/nuopt/glossary/term_c4995faa151e2d66d8ea36c8eaff94885d60c19f.html) [archive.org](https://web.archive.org/web/20200221035313/http://www.msi.co.jp/nuopt/glossary/term_c4995faa151e2d66d8ea36c8eaff94885d60c19f.html) 213 | [^LARSCH]: Larmore, L. L., & Schieber, B. (1991). On-line dynamic programming with applications to the prediction of RNA secondary structure. Journal of Algorithms, 12(3), 490-515. 214 | [^exact]: 厳密には、$c _ {\lambda} (P)$ を最小化する $P$ が複数存在した場合にどれを選ぶかによって、そのような $\lambda$ が存在しない場合もある。その場合、適切な復元を行うなどの対処が必要となる。 215 | [^WQS-binary-search]: [DP optimization - WQS Binary Search Optimization | A Simple Blog](https://robert1003.github.io/2020/02/26/dp-opt-wqs-binary-search.html) [archive.org](https://web.archive.org/web/20210326063417/https://robert1003.github.io/2020/02/26/dp-opt-wqs-binary-search.html)  [archive.org](https://web.archive.org/web/20210326064207/https://codeforces.com/blog/entry/49691) 216 | -------------------------------------------------------------------------------- /_algorithms/dfs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["depth-first search", "DFS"] 14 | level: green 15 | description: 深さ優先探索とは、グラフや木構造の上の探索に用いられるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 深さ優先探索 21 | -------------------------------------------------------------------------------- /_algorithms/dial.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: kuretchi 7 | date: 2021-02-12T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 非負かつ $k$ 以下で整数値の辺重み $c : E \to \lbrace x \in \mathbb{Z} \mid 0 \le x \le k \rbrace$ 付き有向グラフ $G = (V, E)$ および頂点 $s \in V$ 11 | output: > 12 | 各頂点 $t \in V$ に対し $s$-$t$ 最短路長 13 | time_complexity: $O(k \vert V \vert + \vert E \vert)$ 14 | space_complexity: 15 | aliases: 16 | level: red 17 | description: > 18 | Dial's algorithm とは、単一始点最短経路問題を解くアルゴリズムのひとつ。非負かつ最大値の小さい整数重みのグラフについてしか動作しないが、重みの最大値を $k$ として $O(k \vert V \vert + \vert E \vert)$ で動く。キューの持ち方を工夫して Dijkstra 法をさらに高速化したものになっている。0-1 BFS の一般化でもあり、$k = 1$ のときは 0-1 BFS に一致する。 19 | --- 20 | 21 | # Dial's algorithm 22 | 23 | ## 概要 24 | 25 | Dial's algorithm とは、単一始点最短経路問題を解くアルゴリズムのひとつ。非負かつ最大値の小さい整数重みのグラフについてしか動作しないが、重みの最大値を $k$ として $O(k \vert V \vert + \vert E \vert)$ で動く。 26 | 27 | Dial's algorithm は、キューの持ち方を工夫して Dijkstra 法を高速化したものになっている。 28 | 0-1 BFS の一般化でもあり、$k = 1$ のときは 0-1 BFS に一致する。 29 | 30 | ## 詳細 31 | 32 | (省略) 33 | 34 | ## 参考文献 35 | 36 | - Robert B. Dial. 1969. Algorithm 360: shortest-path forest with topological ordering [H]. Commun. ACM 12, 11 (Nov. 1969), 632–633. DOI: 37 | - Dial による提案論文。始点が複数の形で書かれている。また、Dijkstra 法ではなく SPFA を最適化したものとして説明されている。 38 | 39 | ## 関連項目 40 | 41 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 42 | - Dial's algorithm は Dijkstra 法を修正して高速化したものである。 43 | -------------------------------------------------------------------------------- /_algorithms/dijkstra.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: kuretchi 7 | date: 2021-02-12T00:00:00+09:00 8 | - summary: Fibonacci Heap の計測の注釈を変更 9 | authors: noshi91 10 | reviewers: 11 | date: 2021-04-03T18:05:57+09:00 12 | algorithm: 13 | input: > 14 | 非負の辺重み $c : E \to \lbrace x \in \mathbb{R} \mid x \ge 0 \rbrace$ 付き有向グラフ $G = (V, E)$ および頂点 $s \in V$ 15 | output: > 16 | 各頂点 $t \in V$ に対し $s$-$t$ 最短路長 17 | time_complexity: $O(\vert V \vert ^ 2)$ や $O(\vert E \vert \log \vert V \vert)$ など 18 | space_complexity: 19 | aliases: 20 | level: green 21 | description: > 22 | Dijkstra 法とは、単一始点最短経路問題を解くアルゴリズムのひとつ。グラフに負の辺があると動作しない。辺が非負という仮定をもとに動的計画法を利用して高速に動作し、計算量は $O(\vert V \vert ^ 2)$ や $O(\vert E \vert \log \vert V \vert)$ などである。 23 | --- 24 | 25 | # Dijkstra 法 26 | 27 | ## 概要 28 | 29 | Dijkstra 法とは、単一始点最短経路問題を解くアルゴリズムのひとつである。グラフに負の辺があると動作しない。辺が非負という仮定をもとに動的計画法を利用する。 30 | 計算量は、単純な実装では $O(\vert V \vert ^ 2)$ である。優先度付きキューを用いる実装では、優先度付きキューに何を使うかに依存し、Binary Heap を用いた場合は $O(\vert E \vert \log \vert V \vert)$ である。 31 | 32 | 単一始点最短経路問題を解くとは、辺に重みが付いた有向グラフ $G$ と頂点 $s$ が与えられたとき、$s$ を始点とする $s$-$t$ 最短経路をすべての頂点 $t$ に対して求めるということである。 33 | 34 | ## 詳細 35 | 36 | (省略) 37 | 38 | ## その他 39 | 40 | - 高速化のためには優先度付きキューへの push の前の枝刈りが重要である[^yosupo-speedup]。 41 | - Dijkstra 法は辺の重みが整数でかつ最大値が小さいときは優先度付きキューの持ち方を工夫することで計算量を落とせる。この手法は Dial's algorithm と呼ばれる。また特に、辺の重みが $0$ か $1$ のみである場合は 0-1 BFS と呼ばれる[^yosupo-speedup]。 42 | - 辺を逆向きにして終点から Dijkstra 法をするとうまくいくことがある。また、始点と終点の両側からの Dijkstra 法がうまくいくこともある。 43 | - 入力されたグラフを拡張して作った別のグラフ上で Dijkstra 法をするとうまくいくことがよくある。これは「拡張グラフでのダイクストラ法」などと呼ばれる。省略して「拡張ダイクストラ」と呼ばれることもあるが、これは不適切な呼び方であると批判されることが多い[^evima-extended-graph]。 44 | - Fibonacci heap を用いて適切に実装すると計算量が $O(\vert E \vert + \vert V \vert \log \vert V \vert)$ に落ちる。これは競技プログラミングの範囲内でもグラフによっては速いことがある[^rsk0315-fibonacci][^noshi91-fibonacci]。 45 | 46 | ## 参考文献 47 | 48 | - Dijkstra, E.W. A note on two problems in connexion with graphs. Numer. Math. 1, 269–271 (1959). 49 | - Dijkstra による提案論文。再発明された Prim 法の紹介も含んでいる。 50 | 51 | ## 関連項目 52 | 53 | - [動的計画法](/algorithm-encyclopedia/dynamic-programming) 54 | - Dijkstra 法は動的計画法のひとつである。 55 | - Prim 法 56 | - Prim 法は最小全域木を求めるアルゴリズムのひとつであるが、Dijkstra 法と類似している。 57 | - [Bellman-Ford 法](/algorithm-encyclopedia/bellman-ford) 58 | - Bellman-Ford 法は Dijkstra 法と並ぶ単一始点最短経路問題を解くアルゴリズムのひとつである。Dijkstra 法より遅いが、Dijkstra 法とは違って負辺があっても動作する。 59 | - [Shortest Path Faster Algorithm](/algorithm-encyclopedia/spfa) 60 | - Dijkstra 法を優先度付きキューでなく普通のキューを使うように修正するとほとんど SPFA になる。 61 | - [Warshall-Floyd 法](/algorithm-encyclopedia/warshall-floyd) 62 | - Warshall-Floyd 法は全点対間最短経路問題を解くアルゴリズムのひとつである。Dijkstra 法を $\vert V \vert$ 回実行したいような場合には、代わりに Warshall-Floyd 法を使うとよい。 63 | - [Dial's algorithm](/algorithm-encyclopedia/dial) 64 | - 与えられるグラフの辺の重みが整数でかつ最大値が $k$ のとき、この仮定を使って優先度付きキューの持ち方を工夫することで、Dijkstra 法を修正して計算量は $O(k \vert V \vert + \vert E \vert)$ に落とせる。そのように修正したものが Dial's algorithm である。 65 | 66 | ## 外部リンク 67 | 68 | - [色々なダイクストラ高速化 - SlideShare](https://www.slideshare.net/yosupo/ss-46612984)[archive.org](https://web.archive.org/web/20210212144246/https://www.slideshare.net/yosupo/ss-46612984) 69 | - yosupo によるスライド。必須の高速化テクニック (単純な枝刈り) や、辺の重みの整数性を利用した高速化テクニック (Dial's algorithm) などが紹介されている。 70 | - [ダイクストラ法のよくあるミスと落し方 - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2021/02/22/102734)[archive.org](https://web.archive.org/web/20210222035858/https://snuke.hatenablog.com/entry/2021/02/22/102734) 71 | - snuke によるブログ記事。実装ミスをしている Dijkstra 法を撃墜するケースがまとめられている。 72 | 73 | ## 注釈 74 | 75 | [^yosupo-speedup]: [色々なダイクストラ高速化 - SlideShare](https://www.slideshare.net/yosupo/ss-46612984)[archive.org](https://web.archive.org/web/20210212144246/https://www.slideshare.net/yosupo/ss-46612984) 76 | [^evima-extended-graph]: [archive.org](https://web.archive.org/web/20210212131916/https://twitter.com/evima0/status/334678901521530880) 77 | [^rsk0315-fibonacci]: rsk0315 の計測によると [AtCoder Regular Contest 064: E - Cosmic Rays](https://atcoder.jp/contests/arc064/tasks/arc064_c)[archive.org](https://web.archive.org/web/20201101135215/https://atcoder.jp/contests/arc064/tasks/arc064_c) (完全グラフ) では binary heap より Fibonacci heap の方が速い[^fibonacci-vs-naive]。([archive.org](https://web.archive.org/web/20210212142947/https://twitter.com/rsk0315_h4x/status/1188898280459005954)) 78 | [^noshi91-fibonacci]: noshi91 の計測によると、Fibonacci Heap が Binary Heap と $O(\lvert V \rvert ^ 2)$ の実装のいずれよりも高速になるようなグラフが存在する。[Binary Heap を用いた Dijkstra 法の最悪ケースと Fibonacci Heap の計測](https://github.com/noshi91/blog/blob/master/pages/dijkstra_experiment.pdf) [archive.org](https://web.archive.org/web/20210301113825/https://raw.githubusercontent.com/noshi91/blog/master/pages/dijkstra_experiment.pdf) 79 | [^fibonacci-vs-naive]: これは binary heap を用いた一般的な $O(\vert E \vert \log \vert V \vert)$ の実装との比較であり、密グラフでは Fibonacci heap を用いた実装より単純な $O(\vert V \vert ^ 2)$ の実装の方が速い場合が多いことに注意せよ。 80 | -------------------------------------------------------------------------------- /_algorithms/dinic.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-03-30T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | ネットワーク (つまり有向グラフ $G = (V, E)$ および辺容量 $c : E \to \mathbb{R} _ {\ge 0}$ および相異なる頂点 $s, t \in V$) 11 | output: > 12 | $s$-$t$ 最大流 (つまり関数 $f : E \to \mathbb{R} _ {\ge 0}$ であって容量制約とフロー保存則を満たすもの) 13 | time_complexity: > 14 | 最悪計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。ネットワークの構造によっては計算量が落ちることがある。 15 | space_complexity: 16 | aliases: [] 17 | level: blue 18 | description: > 19 | Dinic 法は最大流問題を解くアルゴリズムのひとつ。 20 | 残余グラフ上において、辺の本数の意味での $s$-$t$ 最短経路 DAG を BFS により構成し、増加パスをこの DAG の上の DFS により探して流せるだけ流す、という一連のステップを繰り返す。 21 | 計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。 22 | --- 23 | 24 | # Dinic 法 25 | 26 | ## 概要 27 | 28 | Dinic 法は最大流問題を解くアルゴリズムのひとつである。 29 | 残余グラフ上において、辺の本数の意味での $s$-$t$ 最短経路 DAG を BFS により構成し、増加パスをこの DAG の上の DFS により探して流せるだけ流す、という一連のステップを繰り返す。 30 | 31 | 最悪計算量は $O(\lvert V \rvert^2 \lvert E \rvert)$ だが実用的にはかなり速い。また、ネットワークの構造を制限すれば最悪計算量が落ちることがある[^time-complexity]。 32 | 33 | 34 | ## 詳細 35 | 36 | (省略) 37 | 38 | 39 | ## 関連項目 40 | 41 | - [Ford-Fulkerson 法](/algorithm-encyclopedia/ford-fulkerson) 42 | - Ford-Fulkerson 法は Dinic 法と並んで競技プログラミングでよく利用される最大流問題を解くアルゴリズムのひとつである。Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探すが、Ford-Fulkerson 法では増加パスを単純な DFS により探す。 43 | 44 | 45 | ## 外部リンク 46 | 47 | - [Dinic 法とその時間計算量 - みさわめも](https://misawa.github.io/others/flow/dinic_time_complexity.html)[archive.org](https://web.archive.org/web/20210328020326/https://misawa.github.io/others/flow/dinic_time_complexity.html) 48 | - MiSawa による解説記事。計算量解析について詳しい。 49 | - [最大流問題について. - れんしゅうちょう。 - TopCoder部](https://topcoder-g-hatena-ne-jp.jag-icpc.org/Mi_Sawa/20140311.html)[archive.org](https://web.archive.org/web/20210328021542/https://topcoder-g-hatena-ne-jp.jag-icpc.org/Mi_Sawa/20140311.html) 50 | - MiSawa によるブログ記事。Dinic 法のよくある実装ミスや最悪ケースが紹介されている。 51 | - [競技プログラミングにおける最大流問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/05/09/120217)[archive.org](https://web.archive.org/web/20210328020304/https://blog.hamayanhamayan.com/entry/2017/05/09/120217) 52 | - hamayanhamayan によるブログ記事。例題が列挙されている。 53 | 54 | ## 注釈 55 | 56 | [^time-complexity]: [Dinic 法とその時間計算量 - みさわめも](https://misawa.github.io/others/flow/dinic_time_complexity.html)[archive.org](https://web.archive.org/web/20210328020326/https://misawa.github.io/others/flow/dinic_time_complexity.html) 57 | -------------------------------------------------------------------------------- /_algorithms/doubling.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: | 16 | ダブリングとは、前処理をしておくことによって操作を複数回繰り返した結果を高速に求めるアルゴリズムのひとつ。事前に固定された関数 $f : N \to N$ に対して、関数 $f^0, f^1, f^2, f^4, f^8, \dots, f^{2^{\lfloor \log K \rfloor}}$ を繰り返し二乗法のようにして $O(N \log K)$ で事前に求めておく。すると、クエリとして与えられた $x \in N$ と $K$ 以下の自然数 $k$ に対して、$f^k(x)$ を $O(\log k)$ で求めることができる。これがダブリングである。ただし $N$ とは集合 $\lbrace 0, 1, 2, \dots, N - 1 \rbrace$ のことであり $f^k : N \to N$ は関数 $f^k(x) = \underbrace{f(f(\dots f(} _ {k ~\text{times}} x) \dots))$ のことである。 17 | draft: true 18 | draft_urls: [] 19 | --- 20 | 21 | # ダブリング 22 | -------------------------------------------------------------------------------- /_algorithms/dsu-on-tree.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: Sack 14 | level: orange 15 | description: DSU on tree とは、それぞれの頂点 $x$ に可換 monoid $(M, +, 0)$ の要素の重み $a_x$ のついた木 $T$ のそれぞれの部分木について、その部分木内の重みの総和を全体で $O(n \log n)$ で求めるアルゴリズムである。ただし、その計算の過程において、monoid 演算 $+$ がある要素 $A \in M$ と頂点 $x$ に対し $A + a_x$ という形でしか出現しないという特徴がある。 16 | draft: true 17 | draft_urls: "https://codeforces.com/blog/entry/44351" 18 | --- 19 | 20 | # DSU on tree 21 | -------------------------------------------------------------------------------- /_algorithms/dynamic-programming.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: noshi91 7 | date: 2021-02-23T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["dynamic programming", "DP"] 14 | level: green 15 | description: 動的計画法とは、アルゴリズムの分類のひとつ。対象となる問題を複数の部分問題に分割して、部分問題の答えを記録しながらそのすべてを解くという形のアルゴリズムの総称である。動的計画法に分類されるようなアルゴリズムの実装方法の典型例として、配列をループで埋めていく実装や、メモ化を伴なう再帰による実装がある。 16 | --- 17 | 18 | # 動的計画法 19 | 20 | ## 概要 21 | 22 | 動的計画法 (dynamic programming; DP) はアルゴリズムの分類のひとつである。対象となる問題を複数の部分問題に分割し、部分問題の答えを記録しながらそのすべてを解くという形のアルゴリズムたちを総称して動的計画法と呼ぶ。 23 | 24 | 25 | ## 分類 26 | 27 | 動的計画法に分類されるアルゴリズムたちは、さらに細かく分類することができる。また、そのような分類方法もまたいくつかに分類できる。 28 | 29 | ### 状態にもとづく分類 30 | 31 | - bit DP 32 | - 状態として bitset として表現された集合を持つ DP のこと。bitmask DP などとも呼ばれる。 33 | - 区間 DP 34 | - 状態として区間を持つ DP のこと。 35 | - 木 DP 36 | - なにか根付き木を考え、状態としてその木の部分木を用いる DP のことを木 DP と呼ぶ。[木の畳み込み](https://en.wikipedia.org/wiki/Catamorphism#Tree_fold)などとも呼ばれる。 37 | - 桁 DP 38 | - 状態に数字列の桁が関連するある種の DP のことを桁 DP と呼ぶ。明確な定義はなく、桁が関係していればすべて桁 DP だと考える人もいれば[^uwi-digits][^shojin-comp-digits]、構築途中の数字列がある値を越えるかどうかの判断を状態に含めることが重要だと考える人もいる[^kyort0n-digits]。 39 | - オートマトン DP 40 | - なにかオートマトンを考え、状態としてそのオートマトンの状態を用いる DP のことをオートマトン DP と呼ぶ。 41 | - 連結性 DP 42 | - グラフの接続関係を状態とする DP のこと。 連結 DP や frontier DP や frontier 法風 DP などとも呼ばれる。 43 | - 箱根駅伝 DP 44 | - マッチング (あるいは順列) の個数を数える DP であって「ペアにするのを保留にしている要素の数」を状態の一部に用いる DP のこと。箱根 DP とも呼ばれる。 45 | 46 | ### 値にもとづく分類 47 | 48 | - 確率 DP 49 | - 値が確率であるような DP のこと。 50 | - 期待値 DP 51 | - 値が期待値であるような DP のこと。 52 | 53 | ### 漸化式や実装方法にもとづく分類 54 | 55 | - 配る DP 56 | - 更新する側に注目して書いた漸化式にもとづいて実装される DP のこと。 57 | - 貰う DP 58 | - 更新される側に注目して書いた漸化式にもとづいて実装される DP のこと。 59 | - in-place DP 60 | - DP テーブルを in-place に更新していく DP のこと。セグメント木や convex hull trick を使って高速化できることがある。そこで使われる DP の高速化手法のみを指して in-place DP と呼ばれることもあり、その場合は実家 DP やインライン DP とも呼ばれる。 61 | - 戻す DP 62 | - 漸化式を逆向きに使って更新し、なにかを使わなかった場合の値を求めるような DP のこと。DP の高速化手法のひとつ。 63 | - 挿入 DP 64 | - 列を状態とし、その列に要素を挿入することを遷移とするような DP のこと。逆に抜いていく場合もある。 65 | - 二乗の木 DP 66 | - ある種の木 DP を指す。時間計算量が一見 $O(N^3)$ に見えるが実は $O(N^2)$ になっていることから名前が付いた。 67 | - rerooting 68 | - 木 DP をした結果をもとに、すべての頂点についてその頂点を根だとした場合の値を求める DP のこと。全方位木 DP とも呼ばれる。 69 | - Monge DP 70 | - Monge 性を利用する DP の高速化手法のひとつ。あるいはそれを利用した結果のこと。Knuth optimization とか Knuth-Yao speedup とも呼ばれる。 71 | - Alien DP 72 | - 辺の重みが特定の条件[^snuke-alien]を満たす DAG 上の $2$ 点対間 $k$ 辺最短経路問題のアルゴリズムのこと。二分探索を利用する[^yosupo-alien]。またはこれに帰着して解ける DP のこと。中国では WQS Binary Search と呼ばれているとのことである。 73 | 74 | 75 | ## 関数の再帰的定義による理解 76 | 77 | 再帰的に定義された関数 $f : X \to Y$ をその定義に従って計算するとき、それぞれの $x \in X$ について $y = f(x)$ を記憶しておきちょうど一度のみ計算するようにすれば指数的な爆発を防げ、$O(\vert X \vert)$ 回の漸化式の計算で値が求まる。動的計画法とはこのような事実を利用したアルゴリズムのことである、という見方ができる[^kimiyuki-dp-recursion]。 78 | このとき $X$ は状態の集合であり $Y$ は値の集合である。 79 | 80 | 81 | ## ループとメモ化再帰 82 | 83 | 動的計画法に分類されるようなアルゴリズムの実装方法の典型例として、配列をループで埋めていく実装や、メモ化を伴なう再帰による実装がある。 84 | ただし、競技プログラミングの界隈においては、特に配列をループで埋めていく実装のみを指して動的計画法と呼ばれることもある[^chokudai-memoization]。 85 | 86 | 87 | ## 配る DP と貰う DP 88 | 89 | ほとんどの場合、DP はその漸化式をどのように実装するかによって、貰う DP か配る DP のどちらかに分類できる。 90 | 91 | $y = f(x_0, x_1, x_2, \dots)$ という形で書かれた漸化式をそのまま用いるのが貰う DP である。 92 | 貰う DP の特徴としては、in-place DP などの形の高速化がしやすいことが挙げられる。 93 | 94 | $y = f(x_0, x_1, x_2, \dots)$ という形で書かれた元々の漸化式を逆転させて、$x_0, x_1, x_2, \dots$ のそれぞれを主体として $y \gets g(y, x_0); y \gets g(y, x_1); y \gets g(y, x_2); \dots$ のような更新を行うことで $y$ を計算するのが配る DP である。 95 | 配る DP の特徴としては、遷移関係と処理の向きが一致しており考えやすいことや、添字に負数がでてきにくく実装しやすいことが挙げられる。 96 | 97 | 98 | ## その他 99 | 100 | - 動的計画法は関数の再帰的定義と関係があり、再帰は帰納法と関係がある。帰納法においてはその仮定を強めることでむしろ証明がうまくいくことがあるが、動的計画法においても持つ状態や計算する範囲を増やすことで計算がうまくいくことがある。 101 | - 確率は期待値の特殊な場合と見ることができるため、確率 DP も期待値 DP の特殊な場合だと考えることができる。確率 DP や期待値 DP に特有の技法として、「自己ループを確率分布の期待値で潰す[^furuya1223-loop]」や「十分小さい確率の遷移を無視する[^kuuso1-converge]」などがある。 102 | - 戻す DP の亜種として、関係する要素の影響量や寄与度を計算して修正をする DP がある。 103 | - 有限種類の (計算対象の) 状態を (DP の) 状態とする DP は [Ears](https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d)[archive.org](https://web.archive.org/web/20201101070618/https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d) という問題に由来して「耳 DP」と呼ばれることがある[^tempura-ears][^md19970824-ears]。 104 | - 漸化式が規則的かつ線形になっている DP では、漸化式を行列と見て行列累乗で計算することができる。 105 | - すでに使った区間の集合を管理するような DP では、使った区間同士の間隔をできる限り未決定のままにしておくこと[^example-dwacon6th_prelims_e]や、区間の長さを降順で使うこと[^example-dwacon6th_prelims_e]などがよくある。 106 | 107 | 108 | ## 関連項目 109 | 110 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 111 | - Dijkstra 法は動的計画法に分類される代表的なアルゴリズムのひとつである。 112 | 113 | 114 | ## 外部リンク 115 | 116 | - [プログラミングコンテストでの動的計画法 - SlideShare](https://www.slideshare.net/iwiwi/ss-3578511)[archive.org](https://web.archive.org/web/20200814003001/https://www.slideshare.net/iwiwi/ss-3578511) 117 | - iwiwi による解説スライド 118 | - [DPの話 - aizuzia](https://tayama-2.hatenadiary.org/entry/20111210/1323502092)[archive.org](https://web.archive.org/web/20210107111902/https://tayama-2.hatenadiary.org/entry/20111210/1323502092) 119 | - DP を DAG 上の最短経路を求めることに関連づけて説明した記事 120 | - [競技プログラミングにおける動的計画法更新最適化まとめ(CHT, MongeDP, AlianDP, インラインDP, きたまさ法, 行列累乗) - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/20/234711)[archive.org](https://web.archive.org/web/20210402114657/https://blog.hamayanhamayan.com/entry/2017/03/20/234711) 121 | - hamayanhamayan による DP の問題集 122 | - [「インラインDP」というテクニックに関して - skyaozoraの日記 - TopCoder部](http://topcoder.g.hatena.ne.jp/skyaozora/20171212/1513084670)[archive.org](https://web.archive.org/web/20200113085207/http://topcoder.g.hatena.ne.jp/skyaozora/20171212/1513084670) 123 | - sky58 による in-place DP の高速化の解説記事。この記事が書かれる前は「実家 DP」と呼ばれていたが、この記事によって「インライン DP」で置き換えられたという経緯がある。なお、今ではこの呼び名も不適切だという指摘があり、主に「in-place DP」が代替として用いられている[^sky58-inplace]。 124 | - [戻すDP - sigma425のブログ](http://sigma425.hatenablog.com/entry/2015/07/31/121439)[archive.org](https://web.archive.org/web/20210209142104/http://sigma425.hatenablog.com/entry/2015/07/31/121439) 125 | - sigma425 による戻す DP の解説記事 126 | - [競技プログラミングにおける戻すDP問題 - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/19/154334)[archive.org](https://web.archive.org/web/20210217130302/https://blog.hamayanhamayan.com/entry/2017/03/19/154334) 127 | - hamayanhamayan による戻す DP の問題集 128 | - [International Olympiad in Informatics 2016: day2_3. Aliens](https://ioinformatics.org/files/ioi2016problem6.pdf)[archive.org](https://web.archive.org/web/20191021104945/https://ioinformatics.org/files/ioi2016problem6.pdf) 129 | - Alien DP の語源となった IOI の問題 130 | - [AOJ 2439. 箱根駅伝](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2439)[archive.org](https://web.archive.org/web/20210102030307/http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2439) 131 | - 箱根駅伝 DP の語源となった AOJ の問題 132 | - [二乗の木 DP - (iwi) { 反省します - TopCoder部](https://topcoder.g.hatena.ne.jp/iwiwi/20120428/1335635594)[archive.org](https://web.archive.org/web/20150920041654/https://topcoder.g.hatena.ne.jp/iwiwi/20120428/1335635594) 133 | - iwiwi による二乗の木 DP の解説 134 | - [木と計算量 前編 〜O(N^2)とO(NK)の木DP〜 - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2019/01/15/211812)[archive.org](https://web.archive.org/web/20201211213146/https://snuke.hatenablog.com/entry/2019/01/15/211812) 135 | - snuke による二乗の木 DP の解説 136 | - [AOJ 2439 箱根駅伝 (JAG 夏合宿 2012 day3a-F) (600 点) - けんちょんの競プロ精進記録](https://drken1215.hatenablog.com/entry/2019/10/05/173700)[archive.org](https://web.archive.org/web/20210102014812/https://drken1215.hatenablog.com/entry/2019/10/05/173700) 137 | - drken による箱根駅伝 DP の解説 138 | 139 | 140 | ## 注釈 141 | 142 | [^kimiyuki-dp-recursion]: kimiyuki による記事 [DPそのものとは何であるかを理解する - うさぎ小屋](https://kimiyuki.net/blog/2019/02/11/dp-itself/)[archive.org](https://web.archive.org/web/20210107131727/https://kimiyuki.net/blog/2019/02/11/dp-itself/) 143 | [^furuya1223-loop]: furuya1223 によるツイート [archive.org](https://web.archive.org/web/20191031141515/https://twitter.com/furuya1223/status/1189903074107654145) 144 | [^kuuso1-converge]: kuuso によるツイート [archive.org](https://web.archive.org/web/20191031142007/https://twitter.com/kuuso1/status/1189904707067600901) 145 | [^uwi-digits]: uwi によるツイート [archive.org](https://web.archive.org/web/20200216180244if_/https://twitter.com/uwitenpen/status/1229100036450996224) 146 | [^shojin-comp-digits]: [archive.org](https://web.archive.org/web/20210217113914/https://twitter.com/shojin_comp/status/1229099045475344384) 147 | [^kyort0n-digits]: kort0n によるツイート [archive.org](https://web.archive.org/web/20200216174335/https://twitter.com/kyort0n/status/1229096380431396864) 148 | [^sky58-inplace]: sky58 によるツイート [archive.org](https://web.archive.org/web/20190926110305/https://twitter.com/skyaozora/status/1177173768738705408) 149 | [^tempura-ears]: tempura0224 によるツイート [archive.org](https://web.archive.org/web/20210217132148/https://twitter.com/tempura_cpp/status/1177147483010387968) 150 | [^md19970824-ears]: kanra824 によるツイート [archive.org](https://web.archive.org/web/20200504062557/https://twitter.com/Md19970824/status/1254015456362459137) 151 | [^example-dwacon6th_prelims_e]: 例題: 152 | [^chokudai-memoization]: chokudai によるツイート [archive.org](https://web.archive.org/web/20210217134038/https://twitter.com/chokudai/status/1010049288460570624) 153 | [^snuke-alien]: snuke によるツイート [archive.org](https://web.archive.org/web/20210221081356/https://twitter.com/snuke_/status/928314561890959360) 154 | [^yosupo-alien]: yosupo によるツイート [archive.org](https://web.archive.org/web/20210221064608/https://twitter.com/yosupot/status/928313911891214336) 155 | -------------------------------------------------------------------------------- /_algorithms/eppstein-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: $O(K + E + V \log V)$ 12 | space_complexity: 13 | aliases: 14 | level: black 15 | description: Eppstein's algorithm とは、与えられたグラフ $G$ の $s-t$ 歩道であって $K$ 番目に短いものを $O(K + E + V \log V)$ で求めるアルゴリズムである。 16 | draft: true 17 | draft_urls: "https://qiita.com/nariaki3551/items/0ab83541814f98eab322" 18 | --- 19 | 20 | # Eppstein's algorithm 21 | -------------------------------------------------------------------------------- /_algorithms/euclidean-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 自然数 $a, b$ 10 | output: 最大公約数 $\mathrm{gcd}(a, b)$ 11 | time_complexity: $O(\log a + \log b)$ 12 | space_complexity: 13 | aliases: [] 14 | level: green 15 | description: Euclid の互除法とは、ふたつの自然数の最大公約数を求めるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Euclid の互除法 21 | -------------------------------------------------------------------------------- /_algorithms/fast-fourier-transform.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: $O(n \log n)$ 12 | space_complexity: 13 | aliases: ["fast Fourier transform", "FFT"] 14 | level: yellow 15 | description: 高速 Fourier 変換とは、離散 Fourier 変換を $O(n \log n)$ で行うアルゴリズムである。高速な多項式乗算の実装などに用いられる。 16 | draft: true 17 | draft_urls: 18 | --- 19 | 20 | # 高速 Fourier 変換 21 | -------------------------------------------------------------------------------- /_algorithms/fast-kitamasa-method.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: $k + 1$ 項間の線型漸化式で定まる数列 $a$ の漸化式および初めの $k$ 項 $(a_0, a_1, \dots, a _ {k-1})$ および自然数 $N$ 10 | output: 数列 $a$ の第 $N$ 項 $a_N$ 11 | time_complexity: $O(k \log k \log N)$ 12 | space_complexity: 13 | aliases: 14 | level: red 15 | description: 高速 Kitamasa 法とは、$k + 1$ 項間の線型漸化式で定まる数列の第 $N$ 項を $O(k \log k \log N)$ で求めるアルゴリズムである。Kitamasa 法とは異なる。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 高速 Kitamasa 法 21 | -------------------------------------------------------------------------------- /_algorithms/fast-zeta-transform.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | $n$ 要素の集合 $X$ の部分集合から可換 monoid $M$ への関数 $f : \mathcal{P}(X) \to M$ のグラフ 11 | output: > 12 | 関数 $g(s) = \sum _ {s \subseteq T} f(T)$ のグラフ 13 | time_complexity: $O(n 2^n)$ 14 | space_complexity: 15 | aliases: 16 | level: blue 17 | description: > 18 | 高速 zeta 変換とは、$n$ 要素の集合 $X$ の部分集合から可換 monoid $M$ への関数 $f : \mathcal{P}(X) \to M$ が与えられたとき、関数 $g(s) = \sum _ {s \subseteq T} f(T)$ の全体を $O(n 2^n)$ で求めるアルゴリズムである。累積和の $n$ 次元への一般化と理解できる。 19 | draft: true 20 | draft_urls: ["https://naoyat.hatenablog.jp/entry/zeta-moebius", "https://qiita.com/convexineq/items/afc84dfb9ee4ec4a67d5"] 21 | --- 22 | 23 | # 高速 zeta 変換 24 | -------------------------------------------------------------------------------- /_algorithms/ford-fulkerson.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-03-30T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺容量が整数であるネットワーク (つまり有向グラフ $G = (V, E)$ および辺容量 $c : E \to \mathbb{N}$ および相異なる頂点 $s, t \in V$) 11 | output: > 12 | $s$-$t$ 最大流 (つまり関数 $f : E \to \mathbb{N}$ であって容量制約とフロー保存則を満たすもの) 13 | time_complexity: > 14 | 出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ 15 | space_complexity: 16 | aliases: [] 17 | level: blue 18 | description: > 19 | Ford-Fulkerson 法は最大流問題を解くアルゴリズムのひとつ。 20 | 増加パスを DFS で探してそこにフローを流していくことを繰り返す。 21 | 計算量は出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ である。 22 | --- 23 | 24 | # Ford-Fulkerson 法 25 | 26 | ## 概要 27 | 28 | Ford-Fulkerson 法は最大流問題を解くアルゴリズムのひとつである。 29 | 残余グラフ上で増加パスを DFS で探しそこにフローを流していくことを繰り返す。 30 | 計算量は出力の $s$-$t$ 最大流量を $F$ として $O(F \cdot \lvert E \rvert)$ である。 31 | 32 | 33 | ## 詳細 34 | 35 | (省略) 36 | 37 | 38 | ## 関連項目 39 | 40 | - [Dinic 法](/algorithm-encyclopedia/dinic) 41 | - Dinic 法は Ford-Fulkerson 法と並んで競技プログラミングでよく利用される最大流問題を解くアルゴリズムのひとつである。Ford-Fulkerson 法では増加パスを単純な DFS により探すが、Dinic 法では最短経路 DAG を構成して増加パスをこの DAG の上で探す。 42 | 43 | 44 | ## 外部リンク 45 | 46 | - [競技プログラミングにおける最大流問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/05/09/120217)[archive.org](https://web.archive.org/web/20210328020304/https://blog.hamayanhamayan.com/entry/2017/05/09/120217) 47 | - hamayanhamayan によるブログ記事。例題が列挙されている。 48 | -------------------------------------------------------------------------------- /_algorithms/garner-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 整数と正整数の対の長さ $k$ の列 $((a_0, m_0), (a_1, m_1), \dots, (a _ {k-1}, m _ {k-1}))$ および正整数 $M$ 10 | output: $\forall i. x \equiv a_i \pmod{m_i}$ を満たす $x$ を $M$ で割った余り $x \bmod M$ 11 | time_complexity: $\bmod m_i$ および $\bmod M$ での演算を $O(1)$ と仮定して $O(k^2)$ 12 | space_complexity: 13 | aliases: 14 | level: yellow 15 | description: Garner 法とは、中国剰余定理で存在が示されるところの $\forall i. x \equiv a_i \pmod{m_i}$ を満たす整数 $x$ について、それを別の $M$ で割った余り $x \bmod M$ を求めるアルゴリズムである。計算の過程で現われる整数の大きさが $m_i$ や $M$ の $2$ 乗程度で抑えられることを特徴とする。 16 | draft: true 17 | draft_urls: 18 | --- 19 | 20 | # Garner 法 21 | -------------------------------------------------------------------------------- /_algorithms/heavy-light-decomposition.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["heavy light decomposition", "HL-decomposition", "HLD"] 14 | level: yellow 15 | description: > 16 | 重軽分解とは、根付き木をパスの集合へ分解するテクニックのひとつである。根から始まる最も長いパスをひとつ選んで削除することを再帰的に行う。元々の根付き木上の親子関係によって分解されたパスの集合に木構造を入れたとき、元々の木の高さを $h$ とすると分解されてできた木の高さが $O(\log h)$ になることを特徴とする。 17 | draft: true 18 | draft_urls: "https://math314.hateblo.jp/entry/2014/06/24/220107" 19 | --- 20 | 21 | # 重軽分解 22 | -------------------------------------------------------------------------------- /_algorithms/hill-climbing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-02-28T00:00:00+09:00 8 | tags: algorithm 9 | algorithm: 10 | input: 11 | output: 12 | time_complexity: 13 | space_complexity: 14 | aliases: [] 15 | level: yellow 16 | description: | 17 | 山登り法はグラフ探索アルゴリズムのひとつである。与えられたグラフ上を初期状態となる頂点から初めてランダムウォークのように探索していくが、評価関数 $\varphi : V \to \mathbb{R}$ をあらかじめ固定しておき、評価値が改善する場合のみ遷移をするようにする。貪欲法の一種である。 18 | draft: true 19 | draft_urls: ["http://hakomof.hatenablog.com/entry/2018/12/06/000000"] 20 | --- 21 | 22 | # 山登り法 23 | -------------------------------------------------------------------------------- /_algorithms/imos-method.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: imos 法とは、配列の区間に対する一様なたくさんの操作をまとめて高速に処理するための手法のひとつ。先に操作の結果として起こる差分だけを書き込んでおき、後からまとめて累積和をとることにより操作を全体に作用させる。 16 | draft: true 17 | draft_urls: ["https://imoz.jp/algorithms/imos_method.html"] 18 | --- 19 | 20 | # imos 法 21 | 22 | ## 話題 23 | 24 | - 累積和との関連 25 | - 微積分との関連 26 | - 高次元の場合 27 | -------------------------------------------------------------------------------- /_algorithms/inclusion-exclusion-principle.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: green 15 | description: 包除原理とは、有限集合 $A, B$ について成り立つ $\vert A \cup B \vert = \vert A \vert + \vert B \vert - \vert A \cap B \vert$ という等式のこと。つまり、有限集合 $A, B$ の和集合 $A \cup B$ の要素数を求めるには、$A$ の要素数と $B$ の要素数の和から共通部分 $A \cap B$ の要素数を引けばよいという事実のことである。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # 包除原理 21 | -------------------------------------------------------------------------------- /_algorithms/johnson-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: udon1206 6 | reviewers: noshi91 7 | date: 2021-03-04T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺重み $c : E \to \mathbb{R}$ 付き有向グラフ $G = (V, E)$ であって負閉路を持たないもの 11 | output: > 12 | 各頂点の組 $(s, t) \in V \times V$ に対し $s$-$t$ 最短路長 13 | time_complexity: $O(\lvert V \rvert ^ 2 \log \lvert V \rvert + \lvert V \rvert\lvert E \rvert)$ 14 | space_complexity: $O(\lvert V \rvert + \lvert E \rvert)$ 15 | aliases: [] 16 | level: yellow 17 | description: Johnson のアルゴリズムとは、全点対間最短経路問題を解くアルゴリズムのひとつ。負閉路が存在しない場合に動作する。$O(\lvert V \rvert ^ 2 \log \lvert V \rvert + \lvert V \rvert\lvert E \rvert)$ で動く。 18 | --- 19 | 20 | # Johnson のアルゴリズム 21 | 22 | ## 概要 23 | 24 | Johnson のアルゴリズムとは、全点対間最短経路問題を解くアルゴリズムのひとつ。 25 | 辺重み $c$ 付き有向グラフ $G = (V, E) $ であって負閉路を持たないものを入力とする。 26 | その辺重み $c$ を、以下の2つの性質を満たすように再重み付けをし、辺重み $\hat{c}$ に更新する。 27 | 28 | 1. 任意の頂点の組 $(u, v) \in V \times V$ と任意の $u, v$ 間の道に対して「その道が辺重み $c$ における $u$ から $v$ への最短路であること」と「その道が辺重み $\hat{c}$ における $u$ から $v$ への最短路であること」が同値である。 29 | 30 | 1. $\forall (u, v) \in E, \ \hat{c} (u, v) \geq 0$ 31 | 32 | 再重み付けは、 [Bellman-Ford 法](/algorithm-encyclopedia/bellman-ford)を用いて、$ O(\lvert V \rvert \lvert E \rvert) $ で可能である。再重み付けされたグラフは、辺重みが非負実数であることから、 [Dijkstra 法](/algorithm-encyclopedia/dijkstra) を用いることができるので、$V$ の各頂点において、フィボナッチヒープを用いた [Dijkstra 法](/algorithm-encyclopedia/dijkstra)をすることで、 $O(\lvert V \rvert ^ 2 \log \lvert V \rvert + \lvert V \rvert\lvert E \rvert)$ で全点対間最短経路問題を解くことができる。 33 | 34 | ## グラフの再重み付け 35 | 36 | $G = (V, E)$ を負閉路が存在しない辺重み $c$ 付き有向グラフとする。$G$ に超頂点 $s$ を導入した有向グラフ $G' = (V', E')$ (ただし $V' = V \cup \lbrace s \rbrace$, $E' = E \cup \lbrace(s, v) : v \in V \rbrace$) を考える。全ての $v \in V$ に対して、 $c(s, v) = 0$ と定義し、辺重みを拡張する。このとき、$G$ の任意の頂点の組 $(u, v) \in V \times V$ について、$G'$ での辺重み $c$ における $u$-$v$ 最短経路長は、$G$ での 辺重み $c$ における $u$-$v$ 最短経路長と一致する。このことから、 $G'$ における全点対間最短経路問題を解くことで、 $G$ の全点対間最短経路問題を解くことができる。再重み付けをした辺重み $\hat{c}$ を 37 | $$ 38 | \hat{c}(u,v) = c(u, v) + \delta (s, u) - \delta (s, v) 39 | $$ 40 | のように定義することで、概要で述べた再重み付けの性質を持つことを述べる。ただし、 $\delta (u, v), \ (u, v) \in V' \times V'$ は辺重み $c$ における $u$ から $v$ への最短経路長である。 41 | 42 | ### 性質1. について 43 | 44 | $p = \langle v _ 0, v _ 1, \dots, v _ {k - 1}\rangle$ を $v _ 0$ から $v _ {k - 1}$ への道とする。このとき、辺重み $\hat{c}$ 上での $p$ の経路長は、 45 | $$ 46 | \hat{c} (p) = \displaystyle \sum _ {n = 1} ^ {k - 1} \hat{c} (v _ {n - 1}, v _ {n}) = c(p) + \delta (s, v _ 0) - \delta (s, v _ {k - 1}) 47 | $$ 48 | となる。 $\delta (s, v _ 0), \delta (s, v _ {k - 1})$ は $p$ に依存しないので、 $p$ が辺重み $c$ における $v _ 0$ から $v _ {k - 1}$ の最短経路であることと、 辺重み $\hat{c}$ における $v _ 0$ から $v _ {k - 1}$ の最短経路であることは同値である。 49 | 50 | ### 性質2. について 51 | 52 | 辺重み $c$ において、$G$ が負閉路を持たないとき、 $G'$ も負閉路を持たない。このことから、 53 | $$ 54 | \forall u, v \in V' ,\ \delta (s, v) \leq \delta (s, u) + c(u, v) 55 | $$ 56 | が成り立つ。よって、 57 | $$ 58 | \hat{c}(u,v) = c(u, v) + \delta (s, u) - \delta (s, v) \geq 0 59 | $$ 60 | となる。 61 | 62 | 以上から、 すべての $v \in V'$ における $\delta (s, v)$ が求まれば、グラフの再重み付けをすることができ、これは [Bellman-Ford 法](/algorithm-encyclopedia/bellman-ford) を用いて、 $ O(\lvert V \rvert \lvert E \rvert) $ で可能である。 63 | 64 | ## 関連項目 65 | 66 | - [Warshall-Floyd 法](/algorithm-encyclopedia/warshall-floyd) 67 | - Warshall-Floyd 法は全点対間最短経路問題を解くアルゴリズムのひとつ。定数倍の軽い $O(\lvert V \rvert ^ 3)$ で動く。Johnson のアルゴリズムとは異なる点として、 各頂点の組 $(s, t) \in V \times V$ において、 $s$ から $t$ への経路に負閉路が存在するかを検出できる。 68 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 69 | - Dijkstra 法は単一始点最短経路問題を解くアルゴリズムのひとつ。グラフに重みが負の辺がないときは $\hat{c} = c$ となるため、再重み付けを省略すれば、Johnson のアルゴリズムは各頂点から Dijkstra 法を用いることと一致する。 70 | -------------------------------------------------------------------------------- /_algorithms/karatsuba-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | - summary: 本文作成 9 | authors: ngtkana 10 | reviewers: ["noshi91", "misawa"] 11 | date: 2021-03-30T00:00:00+09:00 12 | algorithm: 13 | input: 14 | 環上の次数 $N - 1$ の多項式 $f, g$ の係数列 15 | output: 16 | 積 $f g$ の係数列 17 | time_complexity: $\Theta ( N ^ { \log _ 2 3 } )$ 回の環演算 18 | space_complexity: 19 | aliases: 20 | level: yellow 21 | description: Karatsuba 法とは、多項式乗算と多倍長整数乗算を $\Theta ( N ^ { \log _ 2 3} )$ 回の環演算で行うアルゴリズムである。 22 | --- 23 | 24 | 25 | # Karatsuba 法 26 | 27 | ## 概要 28 | 29 | Karatsuba 法とは、多項式乗算と多倍長整数乗算を $\Theta ( N ^ { \log _ 2 3} )$ 回の環演算で行うアルゴリズムである。 30 | 31 | 32 | ## 詳細 33 | 34 | 35 | 環 $R$ 上の次数 $N - 1$ の多項式 $f, g$ の積 $f g$ を計算する。これを long multiplication(筆算と同じ方法、grade-school multiplication とも)で計算すると、$\Theta ( N ^ 2 )$ 回の環演算を要する。また、計算量は同じであるが、次のように分割統治法で計算することができる。 36 | 37 | ```plaintext-katex 38 | $\mathtt { LongMultiplication } ( f, g )$ 39 | 1. // 入力: $f, \ g$ は多項式 40 | 2. // 出力: 積 $fg$ 41 | 3. $n = \max ( \mathrm { deg } ( f ), \mathrm { deg } ( g) ) + 1$ 42 | 4. $\mathtt { if } \ n \ \mathtt { == } \ 1$ 43 | 5. $\mathtt { return } \ \left ( [ x ^ 0 ] f \right ) \left ( [ x ^ 0 ] g \right )$ 44 | 6. $m = \lfloor n / 2 \rfloor$ 45 | 7. 次数 $m$ で切って$f ( x ) = f _ 1 (x ) x ^ m + f _ 0 ( x ), g ( x ) = g _ 1 ( x ) x ^ m + g _ 0 ( x )$ と分解する。 46 | 8. $h _ 0 = \mathtt { LongMultiplication }( f _ 0 , g _ 0 )$ 47 | 9. $h _ 1 = \mathtt { LongMultiplication }( f _ 0 , g _ 1 ) + \mathtt { LongMultiplication }( f _ 1, g _ 0 )$ 48 | 10. $h _ 2 = \mathtt { LongMultiplication }( f _ 1 , g _ 1 )$ 49 | 11. $\mathtt { return } \ h _ 2 x ^ { 2 m } + h _ 1 x ^ m + h _ 0$ 50 | ``` 51 | 52 | Karatsuba 法では、恒等式 53 | $$ 54 | f _ 0 g _ 1 + f _ 1 g _ 0 = ( f _ 0 + f _ 1 ) ( g _ 0 + g _ 1 ) - f _ 0 g _ 0 - f _ 1 g _ 1 55 | $$ 56 | を利用する。すると次のような疑似コードを得る。再帰呼出しの回数が $4$ 回から $3$ 回に減り、計算量が $\Theta ( N ^ { \log _ 2 3 } ) \subseteq O ( N ^ { 1.59 } )$ に改善する。 57 | 58 | 59 | ```plaintext-katex 60 | $\mathtt { Karatsuba } ( f, g )$ 61 | 1. // 入力: $f, \ g$ は多項式 62 | 2. // 出力: 積 $fg$ 63 | 3. $n = \max ( \mathrm { deg } ( f ), \mathrm { deg } ( g) ) + 1$ 64 | 4. $\mathtt { if } \ n \ \mathtt { == } \ 1$ 65 | 5. $\mathtt { return } \ \left ( [ x ^ 0 ] f \right ) \left ( [ x ^ 0 ] g \right )$ 66 | 6. $m = \lfloor n / 2 \rfloor$ 67 | 7. 次数 $m$ で切って$f ( x ) = f _ 1 ( x ) x ^ m + f _ 0 ( x ), g ( x ) = g _ 1 ( x ) x ^ m + g _ 0 ( x )$ と分解する。 68 | 8. $h _ 0 = \mathtt { Karatsuba }( f _ 0 , g _ 0 )$ 69 | 9. $h _ 2 = \mathtt { Karatsuba }( f _ 1 , g _ 1 )$ 70 | 10. $h _ 1 = \mathtt { Karatsuba }( f _ 0 + f _ 1, g _ 0 + g _ 1 ) - h _ 0 - h _ 2$ 71 | 11. $\mathtt { return } \ h _ 2 x ^ { 2 m } + h _ 1 x ^ m + h _ 0$ 72 | ``` 73 | 74 | 75 | ## 定数倍について 76 | 77 | Long multiplication は $2 N ^ 2$ 回以下の環演算を行う。 78 | 79 | 一方、Karatsuba 法は、$N$ が $2$ 冪のとき $9 N ^ { \log _ 2 3 }$ 回以下、一般の場合に $21 N ^ { \log _ 2 3 }$ 回以下の環演算を行う。 80 | 81 | ### 証明 82 | 83 | 再帰段階以外では、第 10 行の$f _ 0 + f _ 1, g _ 0 + g _ 1$ の計算に $\lfloor N / 2 \rfloor$ 回ずつ、$\mathtt { Karatsuba } ( f _ 0 + f _ 1, g _ 0 + g _ 1 )$ から $h _ 0, \ h _ 2$ を引くのに $N$ 回以下ずつ、第 11 行で $h _ 2 x ^ { 2 m } + h _ 0$ に $h _ 1 x ^ m$ を足すのに $N$ 回以下、合計 $4 N$ 回以下の環演算を要する。従って、Karatsuba 法の環演算の回数を $T ( N )$ とおくと、$T ( N ) \le 3 T ( \lceil N / 2 \rceil ) + 4 N$ が成り立つ。また $T ( 1 ) = 1$ である。 84 | 85 | したがって $N$ が $2$ 冪のとき、 86 | 87 | $$ 88 | T ( N ) 89 | \le 4 N \sum _ { k = 0 } ^ { \log _ 2 N - 1 } \left ( \frac 3 2 \right ) ^ { k } + 3 ^ { \log _ 2 N } 90 | = 8 N \left ( \left ( \frac 3 2 \right ) ^ { \log _ 2 N } - 1 \right ) + N ^ { \log _ 2 3 } 91 | \le 9 N ^ { \log _ 2 3 } 92 | $$ 93 | 94 | が成り立つ。 95 | 96 | 一方一般の場合は、$L = \lceil \log _ 2 N \rceil$ とおいて、 97 | 98 | $$ 99 | \begin{align*} 100 | T ( N ) 101 | &\le 4 \sum _ { k = 0 } ^ { L - 1 } 3 ^ k \left \lceil \frac N { 2 ^ k } \right \rceil 102 | + 3 ^ L 103 | \le 4 \sum _ { k = 0 } ^ { L - 1 } \left ( N \left ( \frac 3 2 \right ) ^ k + 3 ^ k \right ) 104 | + 3 ^ L 105 | \cr 106 | &= 8 N \left ( \left ( \frac 3 2 \right ) ^ L - 1 \right ) 107 | + 2 \left ( 3 ^ L - 1 \right ) 108 | + 3 ^ L 109 | \cr 110 | &\le 8 N \left ( \left ( \frac 3 2 \right ) ^ { \log _ 2 N + 1 } - 1 \right ) 111 | + 2 \left ( 3 ^ { \log _ 2 N + 1 } - 1 \right ) 112 | + 3 ^ { \log _ 2 N + 1 } 113 | \cr 114 | &= \left ( 12 + 6 + 3 \right ) 3 ^ { \log _ 2 N } - 8 N - 2 115 | \le 21 N ^ { \log _ 2 3 } 116 | \end{align*} 117 | $$ 118 | 119 | が成り立つ。∎ 120 | 121 | ## 多倍長整数の乗算への応用 122 | 123 | 多倍長整数の乗算も、桁数半分で分けて同様の方法で計算することで、高速に計算することができる。 124 | 125 | 126 | ## 参考文献 127 | 128 | * 山本慎 ・三好重明 ・原正雄 ・谷聖一 ・衛藤和文 訳*コンピュータ代数ハンドブック*. 朝倉書店, 2006. 129 | -------------------------------------------------------------------------------- /_algorithms/kitamasa-method.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: $k + 1$ 項間の線型漸化式で定まる数列 $a$ の漸化式および初めの $k$ 項 $(a_0, a_1, \dots, a _ {k-1})$ および自然数 $N$ 10 | output: 数列 $a$ の第 $N$ 項 $a_N$ 11 | time_complexity: $O(k^2 \log N)$ 12 | space_complexity: 13 | aliases: 14 | level: red 15 | description: Kitamasa 法とは、$k + 1$ 項間の線型漸化式で定まる数列の第 $N$ 項を $O(k^2 \log N)$ で求めるアルゴリズムである。高速 Kitamasa 法とは異なる。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Kitamasa 法 21 | -------------------------------------------------------------------------------- /_algorithms/knuth-morris-pratt.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: パターン文字列 $P$ とテキスト文字列 $T$ 10 | output: パターン文字列 $P$ がテキスト文字列 $T$ に含まれるかどうか。含まれるならその位置も求める。 11 | time_complexity: 前処理に $O(\vert P \vert)$ かつ検索に $O(\vert T \vert)$ 12 | space_complexity: 13 | aliases: ["KMP 法"] 14 | level: yellow 15 | description: Knuth-Morris-Pratt 法とは文字列検索アルゴリズムのひとつ。パターン文字列 $P$ の各 prefix について最長の border (prefix かつ suffix であるような文字列) を $O(\vert P \vert)$ で求めておくことで、与えられたテキスト文字列 $T$ に対する検索を $O(\vert T \vert)$ で行う。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Knuth-Morris-Pratt 法 21 | 22 | ## 概要 23 | 24 | Knuth-Morris-Pratt 法とは文字列検索アルゴリズムのひとつ。パターン文字列 $P$ の各 prefix について最長の border (prefix かつ suffix であるような文字列) を $O(\vert P \vert)$ で求めておくことで、与えられたテキスト文字列 $T$ に対する検索を $O(\vert T \vert)$ で行う。 25 | 26 | ## 詳細 27 | 28 | (省略) 29 | 30 | ## 関連項目 31 | 32 | - [Boyer-Moore 法](/algorithm-encyclopedia/boyer-moore) 33 | - Boyer-Moore 法は Knuth-Morris-Pratt 法と並んで競技プログラミングでよく用いられる単一パターン文字列検索アルゴリズムである。 34 | 35 | ## 外部リンク 36 | 37 | - [KMPのK - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2017/07/18/101026)[archive.org](https://web.archive.org/save/https://snuke.hatenablog.com/entry/2017/07/18/101026) 38 | - snuke による解説。 39 | - [MP法とKMP法の違い - 生きたい](https://potetisensei.hatenablog.com/entry/2017/07/10/174908)[archive.org](https://web.archive.org/web/20210305022839/https://potetisensei.hatenablog.com/entry/2017/07/10/174908) 40 | - potetisensei による解説。Morris-Pratt 法と Knuth-Morris-Pratt 法の違いについて説明されている。 41 | - [競技プログラミングにおける文字列アルゴリズム問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/25/005452)[archive.org](https://web.archive.org/web/20210402112827/https://blog.hamayanhamayan.com/entry/2017/03/25/005452) 42 | - hamayanhamayan によるブログ記事。例題が列挙されている。 43 | -------------------------------------------------------------------------------- /_algorithms/knuth-yao-speedup.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: 14 | level: red 15 | description: Knuth-Yao speedup とは、Monge な $N \times N$ 行列 $f$ に対して $\mathrm{dp}(l, r) = \min \lbrace \mathrm{dp}(l, m) + \mathrm{dp}(m + 1, r) \mid l \le m \lt r \rbrace + f(l, r)$ (ただし $l \le r$) で定まる関数 $\mathrm{dp}$ のグラフを $O(N^2)$ で求めるアルゴリズムである。 16 | draft: true 17 | draft_urls: "https://topcoder-g-hatena-ne-jp.jag-icpc.org/spaghetti_source/20120915/1347668163.html" 18 | --- 19 | 20 | # Knuth-Yao speedup 21 | -------------------------------------------------------------------------------- /_algorithms/kruskal.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: Kruskal 法とは、最小全域木を求めるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Kruskal 法 21 | -------------------------------------------------------------------------------- /_algorithms/lagrange-interpolation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | - summary: 見出し修正 9 | authors: noshi91 10 | reviewers: kimiyuki 11 | date: 2021-04-04T10:58:26+09:00 12 | algorithm: 13 | input: 14 | output: 15 | time_complexity: 16 | space_complexity: 17 | aliases: 18 | level: orange 19 | description: > 20 | Lagrange 補間多項式とは、与えられた点群 $\lbrace (x_i, y_i) \mid i \lt N \rbrace$ をすべて通る ($\forall i \lt N. f(x_i) = y_i$ を満たす) ような最小次数の多項式 $f$ のことである。 21 | Lagrange 補間多項式を $\Theta (N (\log N) ^ 2)$ で計算するアルゴリズムが存在する。 22 | draft: true 23 | draft_urls: ["https://rsk0315.hatenablog.com/entry/2020/04/05/203210"] 24 | --- 25 | 26 | # Lagrange 補間多項式 27 | -------------------------------------------------------------------------------- /_algorithms/manacher.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 文字列 $S$ 10 | output: すべての $i$ について、$S$ における $i$ 番目の文字を中心とする最長の回文の半径 11 | time_complexity: $O(\vert S \vert)$ 12 | space_complexity: 13 | aliases: [] 14 | level: blue 15 | description: | 16 | Manacher 法とは、与えられた文字列 $S$ に対して、そのすべての位置 $i$ (ただし $0 \le i \lt \vert S \vert$) について「$S$ における $i$ 番目の文字を中心とする最長の回文の半径」をまとめて $O(\vert S \vert)$ で求めるアルゴリズムのひとつ。そのままでは奇数長の回文についてのみしか求まらない。偶数長の回文についても求めたいときは、$S$ の各文字の間にダミーの文字列を計 $\vert S \vert - 1$ 個挿入してできる文字列 $S'$ に対してもう一度 Manacher 法をすることになる。 17 | draft: true 18 | draft_urls: ["https://snuke.hatenablog.com/entry/2014/12/02/235837"] 19 | --- 20 | 21 | # Manacher 法 22 | 23 | ## 参考文献 24 | 25 | - Glenn Manacher. 1975. A New Linear-Time ``On-Line'' Algorithm for Finding the Smallest Initial Palindrome of a String. J. ACM 22, 3 (July 1975), 346–351. DOI: 26 | - Manacher による最初の論文 27 | - Alberto Apostolico, Dany Breslauer, Zvi Galil, "Parallel detection of all palindromes in a string", Theoretical Computer Science, Volume 141, Issues 1–2, 1995, Pages 163-173, ISSN 0304-3975, . 28 | - Manacher の提案したアルゴリズムが現在の競プロ界隈で知られる形で使えることを示した論文 29 | 30 | ## 外部リンク 31 | 32 | - [文字列の頭良い感じの線形アルゴリズムたち2 - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2014/12/02/235837)[archive.org](https://web.archive.org/web/20210402120040/https://snuke.hatenablog.com/entry/2014/12/02/235837) 33 | - snuke による解説。 34 | - [競技プログラミングにおける文字列アルゴリズム問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/25/005452)[archive.org](https://web.archive.org/web/20210402112827/https://blog.hamayanhamayan.com/entry/2017/03/25/005452) 35 | - hamayanhamayan によるブログ記事。例題が列挙されている。 36 | -------------------------------------------------------------------------------- /_algorithms/meet-in-the-middle.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: たとえば $O(n)$ のものが $O(\sqrt{n} \log n)$ になる 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: 半分全列挙とは、組合せについて処理するときに使えるテクニックのひとつ。すべての要素を考えたときの組合せの全体は列挙するには多すぎるが、半分程度の数の要素に制限して考えたときの組合せであれば列挙できる、という場合に利用可能である。要素の全体をそれぞれ半分程度の大きさのふたつのグループに分け、それぞれのグループについて組合せを全列挙し、それらふたつの結果を組み合わせて全体に対する結果を得る。そのまま全列挙したときの計算量が $O(f(N))$ であるとき、半分全列挙を行ったときの計算量はたとえば $O(\sqrt{f(N)})$ や $O(\sqrt{f(N)} \log f(N))$ などになる。これを利用するアルゴリズムの代表的なものに baby-step giant-step がある。 16 | draft: true 17 | draft_urls: ["https://www.hamayanhamayan.com/entry/2018/01/06/112704"] 18 | --- 19 | 20 | # 半分全列挙 21 | 22 | ## 関連項目 23 | 24 | - baby-step giant-step 25 | - baby-step giant-step は半分全列挙を用いて離散対数問題を解くアルゴリズムである。 26 | 27 | ## 外部リンク 28 | 29 | - [競技プログラミングにおける半分全列挙問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2018/01/06/112704)[archive.org](https://web.archive.org/web/20210402115111/https://blog.hamayanhamayan.com/entry/2018/01/06/112704) 30 | - 例題が多数紹介されている。 31 | -------------------------------------------------------------------------------- /_algorithms/mo-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: "クエリ平方分割" 14 | level: orange 15 | description: > 16 | Mo's algorithm とは、群 $G$ の要素の列 $(a_0, a_1, \dots, a _ {N-1})$ と区間の列 $\lbrack l_0, r_0), \lbrack l_1, r_1), \dots, \lbrack l _ {Q-1}, r _ {Q-1})$ が与えられたとき、それぞれの区間中の要素の総和 $\sum _ {i \in \lbrack l_j, r_j)} a_i$ を全体で $O(N \sqrt{Q})$ あるいは $O((N + Q) \sqrt{N})$ で求めるアルゴリズムである。ただし、その計算の過程において、群の演算 $\cdot$ が要素 $A \in G$ と添字 $i$ に対し $A \cdot a_i, A \cdot a_i^{-1}, a_i \cdot A, a_i^{-1} \cdot A$ のいずれかの形でしか出現しないという特徴がある。 17 | draft: true 18 | draft_urls: ["https://snuke.hatenablog.com/entry/2016/07/01/000000", "https://ei1333.hateblo.jp/entry/2017/09/11/211011"] 19 | --- 20 | 21 | # Mo's algorithm 22 | -------------------------------------------------------------------------------- /_algorithms/monotone-minima.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: noshi91 7 | date: 2020-07-09T00:00:00+09:00 8 | - summary: SMAWK algorithm との類似のある変種についての記述を追加 9 | authors: kimiyuki 10 | reviewers: noshi91 11 | date: 2020-04-03T00:00:00+09:00 12 | algorithm: 13 | input: monotone な $H \times W$ 行列 $f$ 14 | output: 各行 $y$ に対し最小値の位置 $x \in \mathrm{argmin} _ x f(y, x)$ 15 | time_complexity: $O(H + W \log H)$ 16 | space_complexity: 17 | aliases: 18 | level: orange 19 | description: monotone minima とは、monotone な $H \times W$ 行列に対しその各行の最小値を $O(H + W \log H)$ で求めるアルゴリズムである。 20 | --- 21 | 22 | # Monotone minima 23 | 24 | ## 説明 25 | 26 | ### 概要 27 | 28 | monotone minima とは、monotone な $H \times W$ の行列 $f$ に対し、それぞれの行 $y$ の最小値の位置 (のうちのひとつ) $x \in \mathrm{argmin} _ x f(y, x)$ をまとめて効率よく求めるアルゴリズムである。 29 | 愚直には行列全体を走査して $O(H W)$ であるが、これを $O(H + W \log H)$ で行う。 30 | 動作原理は、行列として monotone であるとはそれぞれの列の最小値の位置が左上から右下へと並ぶことであるので、中央付近の行についてその最小値の位置を求めればその右上と左下の区画の探索を省略できるというものである。 31 | 32 | ### 詳細 33 | 34 | 行列に対する monotone の定義は、列に対する monotone (つまり単調性) の定義のひとつの一般化である。 35 | 列に関する (広義) 単調性の定義を関数の記法で書くと、次のような定義になる: 長さ $H$ の数列 $g : H \to A$ が (weakly) monotone であるとは、$y \lt y'$ ならば $g(y) \le g(y')$ であることを言う。 36 | ただし $H, W$ は自然数とし $A$ は全順序集合とする。 37 | これを行列に一般化して、次のような定義になる: $H \times W$ の行列 $f : H \times W \to A$ が (weakly) monotone であるとは、$y \lt y'$ ならば $\forall x \in \mathrm{argmin} _ x f(y, x).~ \exists x' \in \mathrm{argmin} _ {x'} f(y', x').~ x \le x'$ かつ $\forall x' \in \mathrm{argmin} _ {x'} f(y', x').~ \exists x \in \mathrm{argmin} _ x f(y, x').~ x \le x'$ であることを言う。 38 | $\mathrm{argmin} _ x \dots$ が集合であることに注意したい。 39 | 40 | なお、行列の各行が distinct であれば monotone の定義はより単純になる。 41 | 各行が distinct という仮定のもとでは、各行 $y$ ごとにその最小値を含む列が一意に定まるので、これを $x_y$ (ただし $x_y \in \mathrm{argmin} _ x f(y, x)$) とおく。 42 | このとき monotone の定義は次と等しくなる: 各行が distinct な $H \times W$ の行列 $f : H \times W \to A$ が (weakly) monotone であるとは、$y \lt y'$ ならば $x_y \le x _ {y'}$ であることを言う。 43 | つまり、各行が distinct な行列 $f$ が monotone であることは $(x_0, x_1, \dots, x _ {H-1})$ という数列が列として monotone であることと等しい。 44 | 45 | monotone minima の具体的なアルゴリズムは次のようなものである。 46 | 47 | 1. monotone な $f : H \times W \to A$ を (暗な形で) 入力として受け取る。 48 | 1. 中央付近の行 $\bar{y} = \lfloor H / 2 \rfloor$ をとる。これに対して、その行 $\bar{y}$ の最小値を達成する列 $\bar{x} \in \mathrm{argmin} _ x f(\bar{y}, x)$ をなにかひとつ求める。 49 | 1. 行列 $f$ の左上 $H' \times W' = \lbrace 0, 1, \dots, \bar{y} - 1 \rbrace \times \lbrace 0, 1, \dots, \bar{x} \rbrace$ について再帰する。 50 | 1. 行列 $f$ の右下 $H'' \times W'' = \lbrace \bar{y} + 1, \bar{y} + 2, \dots, H - 1 \rbrace \times \lbrace \bar{x}, \bar{x} + 1, \dots, W - 1 \rbrace$ について再帰する。 51 | 1. ステップ (3.) と (2.) と (4.) の結果をまとめ、$H$ 個の行それぞれの最小値の位置を出力として返す。 52 | 53 | 左上への再帰 (ステップ (3.)) において、列を $\lbrace 0, 1, \dots, W - 1 \rbrace$ という全体から $\lbrace 0, 1, \dots, \bar{x} \rbrace$ という $\bar{x} + 1$ 本のみに制限していることは、(weakly) monotone の定義により $y \lt \bar{y}$ ならば $\exists x \in \mathrm{argmin} _ x f(y, x).~ x \le \bar{x}$ であるために正当である。 54 | 右下への再帰についても同様である。 55 | 56 | 計算量について。$O(W)$ かけてある行の最小値の列を求め、$H' \times W'$ と $H'' \times W''$ であって $H' \approx H'' \approx H/2$ かつ $W' + W'' = W + 1$ なふたつの行列に対し再帰している。 57 | これを $H/2 \times W$ なひとつの行列への再帰だと思えば $O(H + W \log H)$ であることが分かる。 58 | 59 | 60 | ## その他 61 | 62 | - 中央付近の行をひとつ選んでその行の最小値を求めその左上と右下について再帰的に解くという形ではなく、奇数行目を無視して偶数行目だけ残した行列についてまず再帰的に解きその後に奇数行目の最小値の位置を補間するという形でも、ほとんど同じアルゴリズムになる。後者の補間をする形のものは [SMAWK algorithm](/algorithm-encyclopedia/smawk-algorithm) から「最小値を含む可能性がないとしてよい列を削除する」というステップを削除してできるアルゴリズムに一致する。 63 | 64 | 65 | ## 関連項目 66 | 67 | - [SMAWK algorithm](/algorithm-encyclopedia/smawk-algorithm) 68 | - SMAWK algorithm は monotone minima の動作に必要な仮定を強めたものになっている。monotone ではなく totally monotone までを仮定して、各行の最小値の位置を $O(H + W)$ で求める。 69 | 70 | ## 外部リンク 71 | 72 | - [Totally Monotone Matrix Searching (SMAWK algorithm) - 週刊 spaghetti_source - TopCoder部](https://topcoder-g-hatena-ne-jp.jag-icpc.org/spaghetti_source/20120923/1348327542.html)[archive.org](https://web.archive.org/web/20201231040117/https://topcoder-g-hatena-ne-jp.jag-icpc.org/spaghetti_source/20120923/1348327542.html) 73 | - tmaehara による解説記事 74 | - [archive.org](https://web.archive.org/web/20210128162922/https://ei1333.github.io/library/dp/monotone-minima.cpp) 75 | - ei13333 による実装例 76 | - [archive.org](https://web.archive.org/web/20210402113454/https://kmyk.github.io/monotone-matrix-visualizer/) 77 | - monotone な行列などを図示してくれるページ 78 | -------------------------------------------------------------------------------- /_algorithms/montgomery-multiplication.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 剰余環の要素 $a, b \in \mathbb{Z}/N\mathbb{Z}$ 10 | output: 積 $ab$ 11 | time_complexity: 設定に依存する 12 | space_complexity: 13 | aliases: 14 | level: red 15 | description: Montgomery 乗算とは、剰余環 $\mathbb{Z}/N\mathbb{Z}$ での乗算を高速に行うアルゴリズムである。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Montgomery乗算 21 | -------------------------------------------------------------------------------- /_algorithms/number-theoretical-transform.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["number-theoretical transform", "NTT", "高速数論変換", "fast modulo transform", "FMT", "高速剰余変換", "整数環FFT"] 14 | level: yellow 15 | description: 数論変換とは、特定の素数 $p$ による剰余環 $\mathbb{Z}/p\mathbb{Z}$ の上で行われる離散Fourier変換と同様の変換のこと、あるいはこの変換を高速Fourier変換と同様に $O(n \log n)$ で行うアルゴリズムのことである。 16 | draft: true 17 | draft_urls: 18 | --- 19 | 20 | # 数論変換 21 | -------------------------------------------------------------------------------- /_algorithms/polynomial-interpolation-geometric.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: noshi91 6 | reviewers: Rogi 7 | date: 2023-04-27T23:53:04+09:00 8 | algorithm: 9 | input: > 10 | 体 $\mathbb{K}$ 上の長さ $n$ の列 $v$、$a, q \in \mathbb{K} \setminus \lbrace 0 \rbrace$。 11 | ただし $q ^ i \neq 1 ~ (1 \leq i \leq n)$ とする。 12 | output: すべての $0 \leq i \lt n$ に対して $f \left( aq ^ i \right) = v _ i$ を満たす $n$ 次未満の多項式 $f$ 13 | time_complexity: $\Theta(n \log(n) )$ 14 | space_complexity: $\Theta(n)$ 15 | aliases: ["inverse chirp z transform", "ICZT"] 16 | level: red 17 | description: > 18 | 標本点が等比数列を成す場合に補間多項式を $\Theta(n \log(n) )$ の時間計算量で計算する。 19 | ただし、$\mathbb{K}$ 上の長さ $n$ の列の畳み込みの時間計算量を $\Theta(n \log(n))$、空間計算量を $\Theta(n)$、$\mathbb{K}$ 上の四則演算を $\Theta(1)$ としている。 20 | 標本点が任意の数列である場合と比べて、$\Theta(\log(n))$ 倍の改善となる。 21 | --- 22 | 23 | # 標本点が等比数列を成す場合に補間多項式を計算するアルゴリズム 24 | 25 | ## 概要 26 | 27 | 標本点が等比数列を成す場合に補間多項式を $\Theta(n \log(n) )$ の時間計算量で計算する。 28 | ただし、$\mathbb{K}$ 上の長さ $n$ の列の畳み込みの時間計算量を $\Theta(n \log(n))$、空間計算量を $\Theta(n)$ としている。 29 | 30 | 標本点が任意の数列である場合と比べて、$\Theta(\log(n))$ 倍の改善となる。 31 | 32 | 本ページでは、Alin Bostan による説明[^Bostan] をもとに、定数倍を改善した計算方法を説明する。 33 | 34 | ### 計算量について仮定していること 35 | 36 | - $\mathbb{K}$ 上の長さ $n$ の列の畳み込みの時間計算量は $\Theta(n \log(n))$ である。 37 | 38 | $\mathbb{K} = \mathbb{F} _ p$ の状況では原始根の計算などが必要になるため、$\Theta(n\log(n))$ を達成するためには適切な前計算が必要となる。 39 | - $\mathbb{K}$ 上の四則演算は $\Theta(1)$ である。 40 | 41 | $\mathbb{K} = \mathbb{F} _ p$ の状況では $\mathbb{K}$ 上の除算が $\Theta(\log(p))$ 掛かるため、この仮定を満たさない。 42 | しかし、$n$ 個の数に対してその乗法についての逆元を $\Theta(n + \log(p))$ で計算するアルゴリズムが存在する。 43 | これを適切に用いることで、全体の時間計算量は $\Theta(n \log(n) + \log(p))$ となる。 44 | 45 | ## 詳細 46 | 47 | まず、$a = 1$ の場合の計算方法を示す。 48 | 求める補間多項式は以下の式で与えられる。 49 | 50 | $$ 51 | f(x) = \sum _ {i = 0} ^ {n - 1} v _ i \frac{\prod _ {j \neq i} \left( x - q ^ j \right)}{\prod _ {j \neq i} \left( q ^ i - q ^ j \right)} 52 | $$ 53 | 54 | 以降の式変形の都合上、$f(x)$ の代わりに $f ^ {\mathrm{R}} (x) \coloneqq x ^ {n - 1} f \left(x ^ {- 1}\right)$ を計算することとする。 55 | これは $f(x)$ の係数を逆向きに並べた多項式であり、以下の式で与えられる。 56 | 57 | $$ \begin{equation} 58 | f ^ {\mathrm{R}} (x) = x ^ {n - 1} \sum _ {i = 0} ^ {n - 1} v _ i \frac{\prod _ {j \neq i} \left( x ^ {- 1} - q ^ j \right)}{\prod _ {j \neq i} \left( q ^ i - q ^ j \right)} 59 | = \sum _ {i = 0} ^ {n - 1} v _ i \frac{\prod _ {j \neq i} \left( 1 - q ^ j x \right)}{\prod _ {j \neq i} \left( q ^ i - q ^ j \right)} 60 | \end{equation} $$ 61 | 62 | $\displaystyle s _ i \coloneqq \prod _ {j = 1} ^ {i} \left( 1 - q ^ j \right)$ と定義すれば、$(1)$ の分母は以下のように表される。 63 | 64 | $$ \begin{equation} \begin{aligned} 65 | \prod _ {j \neq i} \left( q ^ i - q ^ j \right) 66 | &= \left( \prod _ {j \lt i} \left( q ^ i - q ^ j \right) \right) \left( \prod _ {j \gt i} \left( q ^ i - q ^ j \right) \right) \cr 67 | &= \left( \prod _ {j \lt i} q ^ j \left( q ^ {i - j} - 1 \right) \right) \left( \prod _ {j \gt i} q ^ i \left( 1 - q ^ {j - i} \right) \right) \cr 68 | &= \left( (- 1) ^ {i} q ^ {i(i - 1) / 2} \prod _ {j \lt i} \left( 1 - q ^ {i - j} \right) \right) \left( q ^ {i(n - i - 1)} \prod _ {j \gt i} \left( 1 - q ^ {j - i} \right) \right) \cr 69 | &= (- 1) ^ {i} q ^ {i(i - 1) / 2} q ^ {i(n - i - 1)} s _ {i} s _ {n - i - 1} 70 | \end{aligned} \end{equation} $$ 71 | 72 | $q ^ {(i + 1)i / 2} q ^ {(i + 1)(n - (i + 1) - 1)} = q ^ {n - i - 2} \cdot q ^ {i(i - 1) / 2} q ^ {i(n - i - 1)}$ に注意すると、時間計算量 $\Theta(n)$ ですべての $i$ に対して $(2)$ を計算できる。 73 | $\displaystyle w _ i \coloneqq \frac{v _ i}{\prod _ {j \neq i} \left( q ^ i - q ^ j \right)}$ と定義すれば、残る課題は以下の値を計算することである。 74 | 75 | $$ \begin{equation} \begin{aligned} 76 | f ^ {\mathrm{R}} (x) &= \sum _ {i = 0} ^ {n - 1} w _ i \prod _ {j \neq i} \left( 1 - q ^ j x \right) \cr 77 | &= \left(\prod _ {i = 0} ^ {n - 1} \left (1 - q ^ i x \right) \right) \left( \sum _ {i = 0} ^ {n - 1} \frac{w _ i}{1 - q ^ i x} \right) 78 | \end{aligned} \end{equation} $$ 79 | 80 | ### $\displaystyle \prod _ {i = 0} ^ {n - 1} \left (1 - q ^ i x \right)$ の計算 81 | 82 | 証明なしに、以下の事実を認める。 83 | 84 | #### Cauchy Binomial Theorem [^q-binomial] 85 | 86 | $$ 87 | \prod _ {i = 1} ^ {n} \left( 1 + q ^ i y \right) = \sum _ {k = 0} ^ {n} q ^ {k(k + 1) / 2} \binom{n}{k} _ q y ^ k 88 | $$ 89 | 90 | $y = - q ^ {- 1} x$ を代入することで、以下の式を得る 91 | 92 | $$ 93 | \prod _ {i = 0} ^ {n - 1} \left( 1 - q ^ i x \right) = \sum _ {k = 0} ^ {n} (- 1) ^ {k} q ^ {k(k - 1) / 2} \binom{n}{k} _ q x ^ k 94 | $$ 95 | 96 | $q ^ {(k + 1)k / 2} = q ^ k \cdot q ^ {k(k - 1) / 2}$ と $\displaystyle \binom{n}{k} _ q = \frac{s _ n}{s _ k s _ {n - k}}$ を用いると、$\displaystyle \prod _ {i = 0} ^ {n - 1} \left( 1 - q ^ i x \right)$ は $\Theta(n)$ で計算できる。 97 | 98 | ### $\displaystyle \sum _ {i = 0} ^ {n - 1} \frac{w _ i}{1 - q ^ i x}$ の計算 99 | 100 | $\mathbb{K}\lbrack \lbrack x \rbrack \rbrack$ において上の式を $\bmod ~ x ^ n$ で計算できればよい。 101 | 102 | $$ \begin{aligned} 103 | \sum _ {i = 0} ^ {n - 1} \frac{w _ i}{1 - q ^ i x} 104 | &= \sum _ {i = 0} ^ {n - 1} w _ i \sum _ {j = 0} ^ {\infty} \left( q ^ i x \right) ^ j \cr 105 | &= \sum _ {i = 0} ^ {n - 1} \sum _ {j = 0} ^ {\infty} w _ i q ^ {ij} x ^ j \cr 106 | &= \sum _ {j = 0} ^ {\infty} \left( \sum _ {i = 0} ^ {n - 1} w _ i \left( q ^ j \right) ^ i \right) x ^ j 107 | \end{aligned} $$ 108 | 109 | であるから、多項式 $g$ を $\displaystyle g(y) \coloneqq \sum _ {i = 0} ^ {n - 1} w _ i y ^ i$ と定義すれば、$g \left( q ^ j \right)$ が $0 \leq j \lt n$ に対して求まればよい。 110 | これは [chirp z-transform](/algorithm-encyclopedia/chirp-z-transform) を用いて $\Theta(n \log(n) )$ で計算できる。 111 | 112 | 113 | 以上より、$(3)$ の計算を $\Theta(n \log(n) )$ で行うことができる。 114 | $a \neq 1$ の場合は、上記の方法で $f \left( q ^ i \right) = v _ i$ を満たす多項式 $f$ を計算したのち、その $k$ 次の係数を $a ^ {-k}$ 倍することで求める多項式が得られる。 115 | 116 | ## 参考文献 117 | 118 | 1. [Bostan, A. (2010). Fast algorithms for polynomials and matrices. JNCF 2010. Algorithms Project, INRIA.](https://specfun.inria.fr/bostan/publications/exposeJNCF.pdf)[archive.org](https://web.archive.org/web/20221220161514/https://specfun.inria.fr/bostan/publications/exposeJNCF.pdf) 119 | 120 | 1. Bostan, A., & Schost, É. (2005). Polynomial evaluation and interpolation on special sets of points. Journal of Complexity, 21(4), 420-446. 121 | - Newton basis を経由することで、同じく $\Theta(n \log(n) )$ の時間計算量をもつアルゴリズムを導出している。 122 | 123 | ## 注釈 124 | 125 | [^Bostan]: [Bostan, A. (2010). Fast algorithms for polynomials and matrices. JNCF 2010. Algorithms Project, INRIA.](https://specfun.inria.fr/bostan/publications/exposeJNCF.pdf)[archive.org](https://web.archive.org/web/20221220161514/https://specfun.inria.fr/bostan/publications/exposeJNCF.pdf) pp. 48-49 126 | 127 | [^q-binomial]: [Cauchy Binomial Theorem -- from Wolfram MathWorld](https://mathworld.wolfram.com/CauchyBinomialTheorem.html)[archive.org](https://web.archive.org/web/20211112150455/https://mathworld.wolfram.com/CauchyBinomialTheorem.html) 128 | -------------------------------------------------------------------------------- /_algorithms/prim.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: Prim 法とは、最小全域木を求めるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Prim 法 21 | -------------------------------------------------------------------------------- /_algorithms/rabin-karp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | - summary: 記事作成 9 | authors: kimiyuki 10 | reviewers: noshi91 11 | date: 2021-03-09T00:00:00+09:00 12 | algorithm: 13 | input: $k$ 個のすべて長さが等しいパターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ およびテキスト文字列 $T$ 14 | output: パターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ のどれがテキスト文字列 $T$ に含まれるか。含まれるならその位置も求める。 15 | time_complexity: 前処理には $\Theta(\sum \vert P_i \vert)$ など、検索には平均 $O(\vert T \vert)$ など 16 | space_complexity: 17 | aliases: [] 18 | level: blue 19 | description: Rabin-Karp 法とは、複数のパターン文字列をまとめて扱える乱択の文字列検索アルゴリズムのひとつ。$k$ 個のパターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ のそれぞれについて $\Theta(\sum \vert P_i \vert)$ などをかけてハッシュ値を求めておくことで、与えられたテキスト文字列 $T$ に対し平均 $O(\vert T \vert)$ などでこれらの検索ができる。ハッシュ関数は固定ではないが、ローリングハッシュが使われることが多い。 20 | --- 21 | 22 | # Rabin-Karp 法 23 | 24 | ## 概要 25 | 26 | Rabin-Karp 法とは、複数のパターン文字列をまとめて扱える乱択の文字列検索アルゴリズムのひとつ。$k$ 個のすべて長さが等しいパターン文字列 $P_0, P_1, P_2, \dots, P _ {k-1}$ が与えられたとき、性質の良いハッシュ関数 $H$ を用意しておき、パターン文字列のそれぞれについてハッシュ値 $H(P_0), H(P_1), H(P_2), \dots, H(P _ {k-1})$ を $\Theta(\sum \vert P_i \vert)$ などをかけて求めておく。ただし、ハッシュ関数 $H$ の性質が良いとは、与えられた文字列 $T$ に対し、その長さ $\lvert P_i \rvert$ の部分文字列たちについて、それらのハッシュ値のすべてを高速に計算できるということである。このとき、与えられたテキスト文字列 $T$ に対しての検索が期待計算量 $O(\lvert T \rvert)$ などでできる。ハッシュ関数は固定ではないが、ローリングハッシュが使われることが多い。 27 | 28 | Rabin-Karp 法は、競技プログラミング以外では、ハッシュ値が一致したときに文字列が実際に一致しているか愚直に確認する Las Vegas アルゴリズムとして用いられることが通常である[^usually-las-vegas]。 29 | しかし競技プログラミングにおいては、ハッシュ値が一致したときの確認を省略して Monte Carlo アルゴリズムとして用いられることが多い。 30 | また、用途によっては、いずれかのパターン文字列が含まれるかの判定のみやその出現位置をひとつ構成するのみでよい場合と、それぞれのパターン文字列について出現位置をすべて報告する必要がある場合とがある。 31 | これらの組合せは $4$ 通りあるが、ものによっては計算量がすこし変化する。 32 | それぞれのパターン文字列について出現位置をすべて報告することを考えたとき、Las Vegas アルゴリズムの形であれば出現位置の報告ごとに $\Theta(\lvert P_i \rvert)$ かかるので入力によっては計算量は $\Omega(\lvert P_i \rvert \cdot \lvert T \rvert)$ となってしまう[^las-vegas-all-pattern][^las-vegas-all-report-time-complexity]が、Monte Carlo アルゴリズムの形であればなお期待計算量 $O(\lvert T \rvert)$ のままである。 33 | 34 | ## 詳細 35 | 36 | (省略) 37 | 38 | ## メモ 39 | 40 | - ローリングハッシュが文字列を多項式と見るものであることを思い出せば、Rabin-Karp 法は多項式 $f, g$ の等価性 $f = g$ を検査するために乱数 $r$ を用いて $f(r) = g(r)$ を計算しているものだと思うことができる。これには行列 $A, B$ の等価性 $A = B$ 検査の Monte Carlo アルゴリズム[^pfn-matrix-monte-carlo]との類似がある。 41 | - ハッシュ値が一致したときの検証を省略したとしても最悪計算量 $\Theta(\lvert T \rvert)$ とまでは言えない。$T$ の部分文字列 $T'$ に対するハッシュ値 $H(T')$ をパターン文字列についてのハッシュ値 $H(P_0), H(P_1), H(P_2), \dots, H(P _ {k-1})$ と比較する必要があるが、ここにハッシュマップを使う必要があるため、最悪計算量は $\Theta(\lvert T \rvert)$ より悪くなる。パターン文字列がひとつだけならばハッシュマップは不要であり、この場合は最悪計算量 $\Theta(\lvert T \rvert)$ となる。 42 | 43 | ## 参考文献 44 | 45 | - R. M. Karp and M. O. Rabin, "Efficient randomized pattern-matching algorithms," in IBM Journal of Research and Development, vol. 31, no. 2, pp. 249-260, March 1987, doi: [10.1147/rd.312.0249](https://doi.org/10.1147/rd.312.0249). 46 | - Rabin-Karp 法が提案された論文。空間計算量が定数であることを強調しており、パターン文字列が複数の場合についての言及はない。ハッシュ値の衝突とそれによる厳密比較が発生するたびにハッシュ関数を選び直すことが提案されている。 47 | - T. コルメン, C. ライザーソン, R. リベスト, C. シュタイン. アルゴリズムイントロダクション総合版. 近代科学社, 2013, [ISBN978-4-76-490408-8](https://iss.ndl.go.jp/api/openurl?isbn=9784764904088). 48 | - 32.2 節「Rabin-Karp アルゴリズム」で Rabin-Karp 法が説明されている。 49 | 50 | ## 関連項目 51 | 52 | - [Aho-Corasick 法](/algorithm-encyclopedia/aho-corasick) 53 | - Aho-Corasick 法は Rabin-Karp 法と並んで競技プログラミングでよく利用される複数パターン文字列検索アルゴリズムである。 54 | 55 | ## 外部リンク 56 | 57 | - [競技プログラミングにおける文字列アルゴリズム問題まとめ - はまやんはまやんはまやん](https://blog.hamayanhamayan.com/entry/2017/03/25/005452)[archive.org](https://web.archive.org/web/20210402112827/https://blog.hamayanhamayan.com/entry/2017/03/25/005452) 58 | - hamayanhamayan によるブログ記事。例題が列挙されている。 59 | 60 | ## 注釈 61 | 62 | [^usually-las-vegas]: Rabin と Karp による提案論文においてもアルゴリズムイントロダクションでの説明においても、Rabin-Karp 法はハッシュ値が一致したときは厳密比較をするものとして説明されている。 63 | [^las-vegas-all-pattern]: たとえば、パターン文字列とテキスト文字列がすべて同じ文字からなる場合や、パターン文字列がアルファベット $\Sigma$ に対し $\lvert \Sigma \rvert^{\lvert P_i \rvert}$ 個あるような場合など。 64 | [^las-vegas-all-report-time-complexity]: パターン文字列の個数 $k$ が十分小さいもののみを入力として考えれば平均計算量 $\Theta(\lvert T \rvert)$ が言える。 65 | [^pfn-matrix-monte-carlo]: [乱択アルゴリズム紹介(行列乗算の検査&多項式等価性の検査) | Preferred Networks Research & Development](https://tech.preferred.jp/ja/blog/matrix-multiplication-and-polynomial-identity/)[archive.org](https://web.archive.org/web/20210110054323/https://tech.preferred.jp/ja/blog/matrix-multiplication-and-polynomial-identity/) 66 | -------------------------------------------------------------------------------- /_algorithms/recursive-descent.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-03-02T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["recursive descent parsing"] 14 | level: blue 15 | description: 再帰下降構文解析とは、その言語の構文規則に沿った相互再帰的な手続きから構成されるトップダウンな構文解析アルゴリズムのこと。競技プログラミングにおいて要求される構文解析はたいてい再帰下降構文解析で実装できる。 16 | draft: true 17 | draft_urls: ["https://gist.github.com/draftcode/1357281", "https://blog.hamayanhamayan.com/entry/2018/07/13/085956"] 18 | --- 19 | 20 | # 再帰下降構文解析 21 | -------------------------------------------------------------------------------- /_algorithms/rerooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: "全方位木DP" 14 | level: blue 15 | description: > 16 | rerooting とは、根付きでない木 $T$ と根付き木の畳み込み $f$ (いわゆる木 DP) が与えられたとき、それぞれの頂点 $r \in T$ に対しそれを根とした根付き木 $T_r$ に対する畳み込み結果 $f(T_r)$ を $O(N)$ ですべて求めるアルゴリズムである。全方位木 DP とも呼ばれる。 17 | draft: true 18 | draft_urls: "https://ei1333.hateblo.jp/entry/2018/12/21/004022" 19 | --- 20 | 21 | # rerooting 22 | -------------------------------------------------------------------------------- /_algorithms/sieve-of-eratosthenes.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: green 15 | description: Eratosthenes の篩とは、素数判定アルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # Eratosthenes の篩 21 | -------------------------------------------------------------------------------- /_algorithms/simulated-annealing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: MiSawa 7 | date: 2021-02-28T00:00:00+09:00 8 | tags: algorithm 9 | algorithm: 10 | input: 11 | output: 12 | time_complexity: 13 | space_complexity: 14 | aliases: [] 15 | level: yellow 16 | description: 焼きなまし法はグラフ探索アルゴリズムのひとつである。山登り法を改良したものであり、評価値が悪化する場合であっても、評価値の変化量と実行開始からの経過時刻などの関数として定まる確率に従ってランダムにそのような遷移を行う。これには局所最適解から抜け出す効果がある。ビームサーチと並んで、ヒューリスティックコンテストで頻繁に利用されるアルゴリズムである。 17 | draft: true 18 | draft_urls: ["https://shindannin.hatenadiary.com/entry/2021/03/06/115415", "https://qiita.com/tsukammo/items/b410f3202372fe87c919"] 19 | --- 20 | 21 | # 焼きなまし法 22 | -------------------------------------------------------------------------------- /_algorithms/smawk-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: noshi91 7 | date: 2021-02-04T00:00:00+09:00 8 | algorithm: 9 | input: totally monotone な $H \times W$ 行列 $f$ 10 | output: それぞれの行 $y$ に対し最小値の位置 $x \in \mathrm{argmin} _ x f(y, x)$ 11 | time_complexity: $O(H + W)$ 12 | space_complexity: 13 | aliases: ["totally monotone minima", "TM minima"] 14 | level: orange 15 | description: SMAWK algorithm とは、totally monotone な $H \times W$ 行列に対しその各行の最小値を $O(H + W)$ で求めるアルゴリズムである。 16 | --- 17 | 18 | # SMAWK algorithm 19 | 20 | ## 説明 21 | 22 | ### 概要 23 | 24 | SMAWK algorithm とは、totally monotone な $H \times W$ 行列 $f$ に対し、それぞれの行 $y$ の最小値の位置 (のひとつ) $x \in \mathrm{argmin} _ x f(y, x)$ をまとめて効率よく求めるアルゴリズムである。愚直には行列全体を走査して $O(HW)$ であるが、これを $O(H + W)$ で行う。仮定を強めることで monotone minima をより高速にしたようなアルゴリズムである。 25 | 26 | 入力となる行列のそれぞれの行は distinct (重複を持たない) だと仮定されることがあるが、この制約は取り除ける。ただし、ひとつの行に最小値が複数回出現する場合への注意が必要となる。 27 | SMAWK algorithm はそれぞれの行 $y$ について最小値の位置 $x_y$ を出力するが、これを $(x_0, x_1, \dots, x _ {H-1})$ とならべた列は必ず広義単調増加となる。この性質はアルゴリズム自体の内部でも用いられる。 28 | 29 | 30 | ### 詳細 31 | 32 | (省略) 33 | 34 | 35 | ### totally monotone について 36 | 37 | totally monotone の定義について。$H, W$ は自然数とし $A$ は全順序集合とする。$H \times W$ の行列 $f : H \times W \to A$ が totally monotone であるとは、$f$ の任意の $2 \times 2$ 部分行列 $\begin{pmatrix} a & b \cr c & d \end{pmatrix}$ が $c \lt d$ ならば $a \lt b$ を満たしかつ $c = d$ ならば $a \le b$ を満たすこと。 38 | 39 | 定義の対偶のようなものを考えると次が言える: $f$ の任意の $2 \times 2$ 部分行列 $\begin{pmatrix} a & b \cr c & d \end{pmatrix}$ が $a \gt b$ ならば $c \gt d$ を満たしかつ $a = b$ ならば $c \ge d$ を満たす。 40 | また、totally monotone な行列は任意の行や列を削除しても totally monotone なままに保たれる。 41 | 42 | totally monotone であることは $f$ の任意の部分行列が monotone であることと同値である。その自明な場合として、totally monotone な行列は monotone な行列でもあることが言える。 43 | 44 | ## その他 45 | 46 | - 行列 $f$ が陰に保持されるべきことに注意したい。もし陽に保持すると、それだけで空間計算量 $\Theta(HW)$ かかり、自動的に時間計算量も $\Omega(HW)$ になってしまうためである。 47 | - Monge ならば totally monotone である。 48 | - totally monotone ならば monotone である。多少は遅くなるが monotone minima で SMAWK algorithm を代用できる。 49 | - 行列の各行の要素が distinct だと仮定すれば細かい定義の問題を気にしなくてすむ。たとえば SMAWK が提案された 1986 年のプロシーディングでも簡単のためとして distinct を仮定した形の説明がなされている。 50 | - 行列の各行の要素が distinct とは限らない場合の議論は面倒であり、totally monotone や monotone の定義にも揺れがでてくる。SMAWK が提案された 1987 年の論文では distinct を仮定しない形で説明がなされている。 51 | 52 | ## 参考文献 53 | 54 | - A Aggarwal, M Klawe, S Moran, P Shor, and R Wilber. 1986. Geometric applications of a matrix searching algorithm. In Proceedings of the second annual symposium on Computational geometry (SCG '86). Association for Computing Machinery, New York, NY, USA, 285–292. DOI: 55 | - 1987 年の論文が発表される前にあった会議のプロシーディング 56 | - Aggarwal, A., Klawe, M.M., Moran, S. et al. Geometric applications of a matrix-searching algorithm. Algorithmica 2, 195–208 (1987). 57 | - SMAWK algorithm が提案された論文 58 | 59 | 60 | ## 関連項目 61 | 62 | - [Monotone minima](/algorithm-encyclopedia/monotone-minima) 63 | - monotone minima は SMAWK algorithm の動作に必要な仮定を弱めたものになっている。totally monotone ではなく monotone のみを仮定して、各行の最小値の位置を $O(H + W \log H)$ で求める。 64 | 65 | ## 外部リンク 66 | 67 | - [Totally Monotone Matrix Searching (SMAWK algorithm) - 週刊 spaghetti_source - TopCoder部](https://topcoder-g-hatena-ne-jp.jag-icpc.org/spaghetti_source/20120923/1348327542.html)[archive.org](https://web.archive.org/web/20201231040117/https://topcoder-g-hatena-ne-jp.jag-icpc.org/spaghetti_source/20120923/1348327542.html) 68 | - tmaehara による解説記事 69 | - [archive.org](https://web.archive.org/web/20210128162854/https://noshi91.github.io/Library/algorithm/smawk.cpp) 70 | - noshi91 による実装例 71 | - [archive.org](https://web.archive.org/web/20210103162046/http://web.cs.unlv.edu/larmore/Courses/CSC477/monge.pdf) 72 | - [Lawrence L. Larmore](https://en.wikipedia.org/wiki/Lawrence_L._Larmore) による解説 (英語)。具体例を通して説明されている。 73 | - [archive.org](https://web.archive.org/web/20210402113454/https://kmyk.github.io/monotone-matrix-visualizer/) 74 | - totally monotone な行列などを図示してくれるページ 75 | -------------------------------------------------------------------------------- /_algorithms/spfa.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: kuretchi 7 | date: 2021-02-12T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺重み $c : E \to \mathbb{R}$ 付き有向グラフ $G = (V, E)$ および頂点 $s \in V$ 11 | output: > 12 | 各頂点 $t \in V$ に対し $s$-$t$ 最短路長 13 | time_complexity: $O(\vert V \vert \cdot \vert E \vert)$ 14 | space_complexity: 15 | aliases: ["SPFA"] 16 | level: yellow 17 | description: > 18 | Shortest Path Faster Algorithm (SPFA) とは、単一始点最短経路問題を解くアルゴリズムのひとつ。Bellman-Ford 法をキューを使って定数倍高速化したものであり、優先度付きキューでなく普通のキューを使う Dijkstra 法のようなものでもある。計算量は $O(\vert V \vert \cdot \vert E \vert)$ である。 19 | --- 20 | 21 | # Shortest Path Faster Algorithm 22 | 23 | ## 概要 24 | 25 | Shortest Path Faster Algorithm (SPFA) とは、単一始点最短経路問題を解くアルゴリズムのひとつ。Bellman-Ford 法をキューを使って定数倍高速化したものであり、優先度付きキューでなく普通のキューを使う Dijkstra 法のようなものでもある。計算量は $O(\vert V \vert \cdot \vert E \vert)$ である。 26 | 27 | ## 詳細 28 | 29 | (省略) 30 | 31 | ## その他 32 | 33 | - 基本的に常に Bellman-Ford 法より速いようである[^hogloid-speed]。 34 | 35 | ## 関連項目 36 | 37 | - [Bellman-Ford 法](/algorithm-encyclopedia/bellman-ford) 38 | - Bellman-Ford 法をキューを用いて高速化したものが SPFA である。 39 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 40 | - Dijkstra 法を優先度付きキューでなく普通のキューを使うように修正するとほとんど SPFA になる。 41 | 42 | ## 外部リンク 43 | 44 | - [SPFAの紹介 - hogloidのブログ](https://hogloid.hatenablog.com/entry/20120409/1333973448)[archive.org](https://web.archive.org/web/20210402114755/https://hogloid.hatenablog.com/entry/20120409/1333973448) 45 | - hogloid によるブログ記事。簡単な解説と実装例がある。 46 | 47 | ## 注釈 48 | 49 | [^hogloid-speed]: 「少なくともベルマンフォードより遅くなったことはありません」 [SPFAの紹介 - hogloidのブログ](https://hogloid.hatenablog.com/entry/20120409/1333973448)[archive.org](https://web.archive.org/web/20210402114755/https://hogloid.hatenablog.com/entry/20120409/1333973448) 50 | -------------------------------------------------------------------------------- /_algorithms/sqrt-decomposition.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: blue 15 | description: 平方分割とは、長さ $N$ の列を長さ $O(\sqrt{N})$ の列 $O(\sqrt{N})$ 個に分割して処理する手法のこと。 16 | draft: true 17 | draft_urls: ["https://kujira16.hateblo.jp/entry/2016/12/15/000000"] 18 | --- 19 | 20 | # 平方分割 21 | 22 | ## 話題 23 | 24 | - クエリ平方分割 25 | -------------------------------------------------------------------------------- /_algorithms/strongly-connected-components.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: udon1206 6 | reviewers: noshi91 7 | date: 2021-03-04T00:00:00+09:00 8 | algorithm: 9 | input: 有向グラフ $G = (V, E)$ 10 | output: $G = (V, E)$ の強連結成分分解 11 | time_complexity: $O(\lvert V \rvert + \lvert E \rvert)$ 12 | space_complexity: $O(\lvert V \rvert + \lvert E \rvert)$ 13 | aliases: [] 14 | level: blue 15 | description: 有向グラフ $G = (V, E)$ の強連結成分 $C \subseteq V$ は、全ての $(u, v) \in C^2$ について $u$ から $v$ へ到達可能な極大集合である。$G$ の全ての強連結成分は $V$ の分割になり、これを強連結成分分解と呼ぶ。空間計算量、時間計算量ともに $O(\lvert V \rvert + \lvert E \rvert)$ で構成することができる。 16 | --- 17 | 18 | # 強連結成分分解 19 | 20 | ## 概要 21 | 有向グラフ $G = (V, E)$ の強連結成分 $C \subseteq V$ は、全ての $(u, v) \in C^2$ について $u$ から $v$ へ到達可能な極大集合である。$G$ の全ての強連結成分は $V$ の分割になり、これを強連結成分分解と呼ぶ。空間計算量、時間計算量ともに $O(\lvert V \rvert + \lvert E \rvert)$ で構成することができる。実際に構成するアルゴリズムとして、$G$ と $G$ の転置グラフ $G ^ {\top} = (V, E ^ {\top}),\ E ^ {\top} = \lbrace (u,v) : (v, u) \in E \rbrace$ を深さ優先探索する方法[^mathtrain]と、lowlinkに着目して、構成する方法[^acl]がある。 22 | 接続する2頂点が $G$の同じ強連結成分に属する全ての辺を縮約することで得られるグラフが有向非巡回グラフであるという性質がある。 23 | 24 | 25 | ## 注釈 26 | [^mathtrain]: [強連結成分分解の意味とアルゴリズム | 高校数学の美しい物語](https://manabitimes.jp/math/1250)[archive.org](https://web.archive.org/web/20210330212430/https://manabitimes.jp/math/1250) 27 | [^acl]: [AtCoder Library](https://github.com/atcoder/ac-library) の実装はこちらになっている。 28 | -------------------------------------------------------------------------------- /_algorithms/two-pointers.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-01-26T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: cyan 15 | description: しゃくとり法とは、ふたつの添字などを交互に動かして列を走査する手法のこと。 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # しゃくとり法 21 | 22 | ## 話題 23 | 24 | - 形式化の試みについて: 与えられた条件を満たす極大な区間をすべて列挙するものとして理解できる 25 | -------------------------------------------------------------------------------- /_algorithms/warshall-floyd.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: kuretchi 7 | date: 2021-02-12T00:00:00+09:00 8 | algorithm: 9 | input: > 10 | 辺重み $c : E \to \mathbb{R}$ 付き有向グラフ $G = (V, E)$ 11 | output: > 12 | 各頂点の組 $(s, t) \in V \times V$ に対し $s$-$t$ 最短路長 13 | time_complexity: $O(\vert V \vert ^ 3)$ 14 | space_complexity: 15 | aliases: 16 | level: green 17 | description: > 18 | Warshall-Floyd 法とは、全点対間最短経路問題を解くアルゴリズムのひとつ。負閉路が存在するなら検出できる。定数倍の軽い $O(\vert V \vert ^ 3)$ で動く。 19 | --- 20 | 21 | # Warshall-Floyd 法 22 | 23 | ## 概要 24 | 25 | Warshall-Floyd 法とは、全点対間最短経路問題を解くアルゴリズムのひとつ。 26 | 負閉路が存在するなら検出できる。定数倍の軽い $O(\vert V \vert ^ 3)$ で動く。 27 | 28 | 全点対間最短経路問題を解くとは、辺に重みが付いた有向グラフ $G$ が与えられたとき、頂点の組 $(s, t)$ のすべてに対して $s$-$t$ 最短経路を求めるということである。 29 | 30 | ## 詳細 31 | 32 | (省略) 33 | 34 | ## 関連項目 35 | 36 | - [Dijkstra 法](/algorithm-encyclopedia/dijkstra) 37 | - Dijkstra 法は単一始点最短経路問題を解くアルゴリズムのひとつである。競技プログラミングでは Warshall-Floyd 法と並んで頻繁に利用される。 38 | - [Bellman-Ford 法](/algorithm-encyclopedia/bellman-ford) 39 | - Bellman-Ford 法は単一始点最短経路問題を解くアルゴリズムのひとつである。Bellman-Ford 法は緩和を収束するまで繰り返すことで動作するが、これは Warshall-Floyd 法も同様である。 40 | -------------------------------------------------------------------------------- /_algorithms/weighted-union-heuristic.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: ["マージテク", "デマテク"] 14 | level: cyan 15 | description: weighted-union heuristic とは、ふたつの集まりの間で要素を移動させてひとつにまとめる操作を繰り返す際に、常に要素が少ない方から多い方へと移すようにすると計算量が落ちるというテクである。具体的には、大きさ $a$ のものを大きさ $b$ のものへと $O(a)$ かけてマージし (中身を移し) て大きさ $a + b$ のものを作るという操作を使って、大きさの合計が $n$ であるようないくつかのものをひとつにマージしてまとめたいというような状況において、合計の計算量 $O(n \log n)$ でこれが可能である。データ構造をマージする一般的なテクとも呼ばれる。 16 | draft: true 17 | draft_urls: "https://web.archive.org/web/20181213115442/https://topcoder.g.hatena.ne.jp/iwiwi/20131226/1388062106" 18 | --- 19 | 20 | # weighted-union heuristic 21 | -------------------------------------------------------------------------------- /_algorithms/yen-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-07-09T00:00:00+09:00 8 | algorithm: 9 | input: 有向あるいは無向グラフ $G$ とその頂点 $s, t$ および自然数 $K$ 10 | output: $G$ の $s-t$ 単純路であって $K$ 番目に短いもの 11 | time_complexity: $O(K V (E + V) \log V)$ 12 | space_complexity: 13 | aliases: 14 | level: black 15 | description: Yen's algorithm とは、与えられたグラフ $G$ の $s-t$ 単純路であって $K$ 番目に短いものを $O(K V (E + V) \log V)$ で求めるアルゴリズムである。 16 | draft: true 17 | draft_urls: "https://qiita.com/nariaki3551/items/821dc6ffdc552d3d5f22" 18 | --- 19 | 20 | # Yen's algorithm 21 | -------------------------------------------------------------------------------- /_algorithms/z-algorithm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2021-02-05T00:00:00+09:00 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: orange 15 | description: Z algorithm とは、与えられた文字列 $S$ に対して、文字列 $S$ の $i$ 文字目以降の文字列 $S\lbrack i \colon \rbrack = (S _ i, S _ {i + 1}, \dots, S _ {\vert S \vert - 1})$ を考えたときの、すべての $i$ について「$S$ と $S\lbrack i \colon \rbrack$ の最長共通接頭辞の長さ」をまとめて $O(\vert S \vert)$ で求めるアルゴリズムのひとつ。 16 | draft: true 17 | draft_urls: ["https://snuke.hatenablog.com/entry/2014/12/03/214243"] 18 | --- 19 | 20 | # Z algorithm 21 | 22 | - [文字列の頭良い感じの線形アルゴリズムたち3 - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ](https://snuke.hatenablog.com/entry/2014/12/03/214243)[archive.org](https://web.archive.org/web/20210309135606/https://snuke.hatenablog.com/entry/2014/12/03/214243) 23 | - snuke による解説 24 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely need to edit after that. 5 | # For technical reasons, this file is *NOT* reloaded automatically when you use 6 | # 'jekyll serve'. If you change this file, please restart the server process. 7 | 8 | # Site settings 9 | title: "Kyopro Encyclopedia of Algorithms" 10 | email: noshi91d@gmail.com 11 | author: "noshi91" 12 | description: 13 | baseurl: "/algorithm-encyclopedia" # the subpath of your site, e.g. /blog 14 | url: "https://noshi91.github.io" # the base hostname & protocol for your site 15 | exclude: 16 | - "/.bundle" 17 | - "/.vendor" 18 | - "/Gemfile" 19 | - "/Gemfile.lock" 20 | - "/.git" 21 | - "/.github" 22 | - "/.gitignore" 23 | - "/README.md" 24 | - "/DESIGN.md" 25 | - "/CONTRIBUTING.md" 26 | - "/scripts" 27 | 28 | # Build settings 29 | markdown: kramdown 30 | kramdown: 31 | smart_quotes: ["apos", "apos", "quot", "quot"] 32 | permalink: /:categories/:year/:month/:day/:title 33 | future: true 34 | timezone: Asia/Tokyo 35 | 36 | # Collections settings 37 | collections: 38 | algorithms: 39 | permalink: /:title 40 | sort_by: title 41 | output: true 42 | tenkeis: 43 | permalink: /tenkei/:title 44 | sort_by: title 45 | output: true 46 | 47 | theme: jekyll-theme-primer 48 | 49 | plugins: 50 | # default on GitHub pages 51 | - jekyll-coffeescript 52 | - jekyll-default-layout 53 | - jekyll-gist 54 | - jekyll-github-metadata 55 | - jekyll-optional-front-matter 56 | - jekyll-paginate 57 | - jekyll-readme-index 58 | - jekyll-titles-from-headings 59 | - jekyll-relative-links 60 | # additional plugins 61 | - jekyll-octicons 62 | - jekyll-redirect-from 63 | - jekyll-sitemap 64 | 65 | titles_from_headings: 66 | strip_title: true 67 | collections: true 68 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% if page.draft %}{% endif %} 8 | 9 | {% seo %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 52 | 53 | 54 |
55 |

56 | {% if page.title contains site.title %} 57 | {{ page.title }} 58 | {% elsif site.title %} 59 | {% if page.algorithm.level %}{% endif %} 60 | {{ page.title }} 61 | 62 |
63 | {{ site.title }} 64 |
65 | {% endif %} 66 |

67 | 68 |
69 | これはステージング環境です。5 秒後に自動的に本番環境 ({{ "" | absolute_url }}) にリダイレクトされます。リダイレクトを抑止したい場合は #noredirect を付けた URL {{ page.url | relative_url }}#noredirect を利用してください。 70 |
71 | 85 | 86 |
87 | {{ content }} 88 |
89 | 90 | 109 | 110 | 119 | 120 | {% if site.github.private != true and site.github.license %} 121 | 124 | {% endif %} 125 |
126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /_layouts/entry.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {% if page.draft %} 6 |
7 | このページは下書きです。5 秒後に自動的にトップページ ({{ "" | relative_url }}) にリダイレクトされます。リダイレクトを抑止したい場合は #noredirect を付けた URL {{ page.url | relative_url }}#noredirect を利用してください。 8 |
9 | 16 | {% endif %} 17 | 18 |
19 |
20 |
name
{{ page.title }}
21 |
short description
{{ page.description }}
22 | {% if page.algorithm %} 23 | {% if page.algorithm.input %}
input
{{ page.algorithm.input }}
{% endif %} 24 | {% if page.algorithm.pre_condition %}
pre-condition
{{ page.algorithm.pre_condition }}
{% endif %} 25 | {% if page.algorithm.output %}
output
{{ page.algorithm.output }}
{% endif %} 26 | {% if page.algorithm.post_condition %}
post-condition
{{ page.algorithm.post_condition }}
{% endif %} 27 | {% if page.algorithm.condition %}
condition
{{ page.algorithm.condition }}
{% endif %} 28 | {% if page.algorithm.time_complexity %}
time complexity
{{ page.algorithm.time_complexity }}
{% endif %} 29 | {% if page.algorithm.space_complexity %}
space complexity
{{ page.algorithm.space_complexity }}
{% endif %} 30 | {% assign aliases_size = entry.algorithm.aliases | size %} 31 | {% if aliases_size != 0 %} 32 | {% if page.algorithm.aliases %}
aliases
{% for alias in page.algorithm.aliases %}
{{ alias }}
{% endfor %}{% endif %} 33 | {% endif %} 34 | {% endif %} 35 |
36 |
37 |
38 | 39 | {{ content }} 40 | 41 |
42 | 43 | 50 | 51 | 76 | -------------------------------------------------------------------------------- /_sass/rating-colors.scss: -------------------------------------------------------------------------------- 1 | // colors used in AtCoder 2 | $rating-color-grey: #808080; 3 | $rating-color-brown: #804000; 4 | $rating-color-green: #008000; 5 | $rating-color-cyan: #00c0c0; 6 | $rating-color-blue: #0000ff; 7 | $rating-color-yellow: #c0c000; 8 | $rating-color-orange: #ff8000; 9 | $rating-color-red: #ff0000; 10 | $rating-color-black: #000000; 11 | 12 | .rating-color-grey { 13 | color: $rating-color-grey; 14 | } 15 | .rating-color-brown { 16 | color: $rating-color-brown; 17 | } 18 | .rating-color-green { 19 | color: $rating-color-green; 20 | } 21 | .rating-color-cyan { 22 | color: $rating-color-cyan; 23 | } 24 | .rating-color-blue { 25 | color: $rating-color-blue; 26 | } 27 | .rating-color-yellow { 28 | color: $rating-color-yellow; 29 | } 30 | .rating-color-orange { 31 | color: $rating-color-orange; 32 | } 33 | .rating-color-red { 34 | color: $rating-color-red; 35 | } 36 | .rating-color-black { 37 | color: $rating-color-black; 38 | } 39 | -------------------------------------------------------------------------------- /_sass/style.scss: -------------------------------------------------------------------------------- 1 | @import "jekyll-theme-primer"; 2 | 3 | @import "rating-colors"; 4 | @import "user-colors"; 5 | 6 | // toppage link 7 | .toppage-link { 8 | font-size: small; 9 | font-weight: normal; 10 | } 11 | 12 | // the details in the index page 13 | .algorithm-index-details > summary::-webkit-details-marker { 14 | color: grey; 15 | font-size: 60%; 16 | } 17 | 18 | 19 | // algorithm data 20 | .algorithm-data { 21 | color: grey; 22 | font-size: small; 23 | } 24 | 25 | // footer links 26 | .footer-links { 27 | float: right; 28 | color: grey; 29 | font-size: small; 30 | } 31 | 32 | // entry metadata 33 | .entry-metadata { 34 | color: grey; 35 | font-size: small; 36 | } 37 | .entry-metadata .no-authors { 38 | border-bottom: solid 2px red; 39 | } 40 | .entry-metadata .no-reviewers { 41 | border-bottom: solid 2px red; 42 | } 43 | .entry-metadata dt { 44 | clear: left; 45 | } 46 | .entry-metadata dd { 47 | float: left; 48 | } 49 | .entry-metadata dl::after { 50 | content: ""; 51 | display: block; 52 | clear: both; 53 | } 54 | 55 | // links in index.md 56 | a.draft-link { 57 | color: black; 58 | } 59 | .draft-link-container svg.octicon-link { 60 | visibility: hidden; 61 | } 62 | .draft-link-external svg.octicon-link-external { 63 | fill: currentColor; 64 | } 65 | a.draft-link:hover { 66 | text-decoration: none; 67 | } 68 | .draft-link-container:hover svg.octicon-link { 69 | visibility: visible; 70 | fill: grey; 71 | } 72 | 73 | // footer links 74 | #staging-environment-warning { 75 | color: red; 76 | font-size: large; 77 | } 78 | #staging-environment-warning.production-environment { 79 | display: none; 80 | } 81 | -------------------------------------------------------------------------------- /_sass/user-colors.scss: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED BY user-ratings.py! DO NOT EDIT! 2 | @import "rating-colors"; 3 | .handle { font-weight: bold; } 4 | .user-MiSawa { color: $rating-color-green; } 5 | .user-Rogi { color: $rating-color-blue; } 6 | .user-chokudai { color: $rating-color-red; } 7 | .user-drken { color: $rating-color-orange; } 8 | .user-ei13333 { color: $rating-color-orange; } 9 | .user-furuya1223 { color: $rating-color-yellow; } 10 | .user-hadrori { color: $rating-color-black; } 11 | .user-hamayanhamayan { color: $rating-color-yellow; } 12 | .user-hogloid { color: $rating-color-red; } 13 | .user-hos_lyric { color: $rating-color-red; } 14 | .user-iwiwi { color: $rating-color-black; } 15 | .user-kanra824 { color: $rating-color-yellow; } 16 | .user-kimiyuki { color: $rating-color-orange; } 17 | .user-kort0n { color: $rating-color-red; } 18 | .user-kuretchi { color: $rating-color-blue; } 19 | .user-kuuso { color: $rating-color-blue; } 20 | .user-minaminao { color: $rating-color-yellow; } 21 | .user-misawa { color: $rating-color-green; } 22 | .user-ngtkana { color: $rating-color-orange; } 23 | .user-noshi91 { color: $rating-color-red; } 24 | .user-potetisensei { color: $rating-color-orange; } 25 | .user-rsk0315 { color: $rating-color-yellow; } 26 | .user-sigma425 { color: $rating-color-red; } 27 | .user-sky58 { color: $rating-color-red; } 28 | .user-snuke { color: $rating-color-red; } 29 | .user-tempura0224 { color: $rating-color-red; } 30 | .user-tmaehara { color: $rating-color-black; } 31 | .user-udon1206 { color: $rating-color-yellow; } 32 | .user-uwi { color: $rating-color-red; } 33 | .user-yaketake08 { color: $rating-color-yellow; } 34 | .user-yosupo { color: $rating-color-red; } 35 | -------------------------------------------------------------------------------- /_tenkeis/45-rotation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 45 度回転とは、入力として与えられた $2$ 次元平面の点 $(x, y)$ を $(x-y, x+y)$ や $(x+y, x-y)$ に変換してから扱うこと。 9 | draft: true 10 | draft_urls: ["https://kagamiz.hatenablog.com/entry/2014/12/21/213931"] 11 | --- 12 | 13 | # 45 度回転 14 | -------------------------------------------------------------------------------- /_tenkeis/bininary-search-the-answer.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 二分探索を用いると「得られる点数の最大値を求める」という最大化問題を「ある点数を得ることは可能か求める」という判定問題に帰着させられる。 9 | draft: true 10 | draft_urls: ["https://betrue12.hateblo.jp/entry/2019/05/11/013403"] 11 | --- 12 | 13 | # 答えの二分探索 14 | 15 | ## 例題 16 | 17 | - [AtCoder Beginner Contest 144: D - Water Bottle](https://atcoder.jp/contests/abc144/tasks/abc144_d)[archive.org](https://web.archive.org/web/20201101133409/https://atcoder.jp/contests/abc144/tasks/abc144_d) 18 | - 実装をさぼるのに使える 19 | - [AtCoder Beginner Contest 144: E - Gluttony](https://atcoder.jp/contests/abc144/tasks/abc144_e)[archive.org](https://web.archive.org/web/20210116115422/https://atcoder.jp/contests/abc144/tasks/abc144_e) 20 | 21 | ## リンク 22 | 23 | - [「答えを決め打つ」タイプの二分探索を使いこなそう - ARMERIA](https://betrue12.hateblo.jp/entry/2019/05/11/013403)[archive.org](https://web.archive.org/web/20201113061329/https://betrue12.hateblo.jp/entry/2019/05/11/013403) 24 | -------------------------------------------------------------------------------- /_tenkeis/bitmask-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | algorithm: 9 | aliases: ["bitmask DP"] 10 | description: bit DP とは、状態として集合を用いる DP であって、特にその集合を bitset として扱うもののこと。状態の持ちかたによる DP の分類のひとつ。 11 | draft: true 12 | draft_urls: [] 13 | --- 14 | 15 | # bit DP 16 | -------------------------------------------------------------------------------- /_tenkeis/counting-by-complement.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 補集合を数えるとは、ある条件を満たす要素の個数を求めることを、ある条件を満たさない要素の個数を求めることによって行うテクニックのこと。 9 | --- 10 | 11 | # 補集合を数える 12 | 13 | 補集合を数えるとは、ある条件を満たす要素の個数を求めることを、ある条件を満たさない要素の個数を求めることによって行うテクニックのこと。 14 | 「集合 $X$ の要素 $x \in X$ であって $\varphi(x)$ を満たすものを数えよ」という問題を「集合 $X$ の要素数を数えよ」「集合 $X$ の要素 $x \in X$ であって $\lnot \varphi(x)$ を満たすものを数えよ」というふたつの問題に帰着させられる。 15 | -------------------------------------------------------------------------------- /_tenkeis/event-sort.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: イベントソートとは、クエリを時刻順にソートして順番に処理するテクニックのこと。 9 | --- 10 | 11 | # イベントソート 12 | 13 | イベントソートとは、クエリをそれに関連する時刻や位置の順にソートして順番に処理するテクニックのこと。 14 | 基本的にオフラインクエリに対して使うことになる。 15 | 16 | ## 例題 17 | 18 | - [AtCoder Beginner Contest 128: E - Roadwork](https://atcoder.jp/contests/abc128/tasks/abc128_e)[archive.org](https://web.archive.org/web/20201124012909/https://atcoder.jp/contests/abc128/tasks/abc128_e) 19 | - この問題の解説において命名された。 20 | - [AOJ 1297: Swimming Jam](https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1297)[archive.org](https://web.archive.org/web/20170714105730/https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1297) 21 | 22 | ## 命名者について 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /_tenkeis/gyaku-shori.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: なにかを順番に処理するとき、逆から処理するとうまくいくことがある。union-find 木などのような、追加はできるが削除はできない構造を使う場合に多い。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 逆から考える 14 | -------------------------------------------------------------------------------- /_tenkeis/gyou-retsu-tyouten.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 大きさ $H \times W$ のマス目の上のなにかの連結性を考えるなどの場合に、行と列のそれぞれに対応する $H + W$ 個の追加の頂点を考えるとうまくいくことがある。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 行や列に対応する頂点を作る (名称募集中) 14 | -------------------------------------------------------------------------------- /_tenkeis/hakoneekiden-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 記事作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | algorithm: 9 | aliases: ["箱根DP", "箱根駅伝", "箱根"] 10 | description: 区間の集合を構成するような DP であって「左端は決まったが右端はまだ決まってない区間の数」と「右端は決まったが左端はまだ決まってない区間の数」を状態とする DP のこと。 11 | --- 12 | 13 | # 箱根駅伝 DP 14 | 15 | 箱根駅伝 DP とは、区間の集合を構成するような DP であって「左端は決まったが右端はまだ決まってない区間の数」と「右端は決まったが左端はまだ決まってない区間の数」を状態とする DP のこと。状態が何であるかに基づく DP の分類のひとつ。 16 | 17 | ## 例題 18 | 19 | - [AOJ 2439: 箱根駅伝](https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2439)[archive.org](https://web.archive.org/web/20210102030307/https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2439) 20 | - この問題が呼称の由来である。 21 | - [AtCoder Beginner Contest 134: F - Permutation Oddness](https://atcoder.jp/contests/abc134/tasks/abc134_f)[archive.org](https://web.archive.org/web/20201203225527/https://atcoder.jp/contests/abc134/tasks/abc134_f) 22 | -------------------------------------------------------------------------------- /_tenkeis/in-place-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | algorithm: 9 | aliases: ["インラインDP", "実家DP"] 10 | description: in-place DP とは、セグメント木や convex hull trick を用いて DP を高速化すること。。DP の高速化手法のひとつ。あるいは、実装方法に基づく DP の分類のひとつ。 11 | draft: true 12 | draft_urls: ["https://web.archive.org/web/20200113085207/http://topcoder.g.hatena.ne.jp/skyaozora/20171212/1513084670"] 13 | --- 14 | 15 | # in-place DP 16 | -------------------------------------------------------------------------------- /_tenkeis/kakuchou-graph.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 拡張グラフとは、もともと与えられたグラフを何らかの方法で拡張したグラフのこと。もともとの頂点の集合 $V$ と時刻の集合 $\lbrace 0, 1, \dots, T - 1 \rbrace$ の直積 $V' = V \times \lbrace 0, 1, \dots, T - 1 \rbrace$ を新しいグラフの頂点集合とすることが多い。たいてい Dijkstra 法と共に用いられることが多い。 9 | draft: true 10 | draft_urls: ["http://tutuz.hateblo.jp/entry/2019/01/26/134215"] 11 | --- 12 | 13 | # 拡張グラフ 14 | -------------------------------------------------------------------------------- /_tenkeis/keta-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 桁 DP とは、自然数の \(10\) 進数展開などを桁ごとに決定していくような DP のこと。状態の持ちかたによる DP の分類のひとつ。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 桁 DP 14 | 15 | 桁 DP とは、自然数の \(10\) 進数展開などを桁ごとに決定していくような DP のこと。おそらくは状態の持ちかたによる DP の分類のひとつ。 16 | 17 | 特に「自然数 $n \lt L$ であって条件 $\varphi(n)$ を満たすものの個数を求めよ」のような形式の問題の際によく現れる。 18 | このときは「現時点までずっと $L$ と一致している」場合の (あるひとつの) 値と「もう $L$ より真に小さいことが確定した」場合の値たちとを管理すればよい。 19 | 20 | ## 例題 21 | 22 | - [AtCoder Beginner Contest 129: E - Sum Equals Xor](https://atcoder.jp/contests/abc129/tasks/abc129_e)[archive.org](https://web.archive.org/web/20210121051948/https://atcoder.jp/contests/abc129/tasks/abc129_e) 23 | 24 | 25 | ## 厳密な定義について 26 | 27 | 厳密な定義はかなり揺れる。構成途中の文字列を状態とする DP や、数字列 (あるいは記号の種類数が少ない文字列) 上のオートマトン DP と理解されることもある。 「境界となる自然数 $N より小さくなることが確定したか」のフラグを状態とする DP だと言う人もいる。 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /_tenkeis/kihonteiri-kityaku.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 「区間 $\lbrack l, r)$ に含まれる整数 $x \in \lbrack l, r)$ であって条件 $\varphi(x)$ を満たすものの個数を求めよ」という問題は「$n$ 未満の自然数 $x \in n$ であって条件 $\varphi(x)$ を満たすものの個数を求めよ」という問題に帰着するとよい。微分積分学の基本定理を思い出すとよい。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 区間から始切片への帰着 (名称募集中) 14 | -------------------------------------------------------------------------------- /_tenkeis/min-saiki-bunkatsu.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 列に対する値を求めたいとき、列をその最小値で分割して再帰的に計算するとうまくいくことがある。 9 | draft: true 10 | draft_urls: ["https://kimiyuki.net/blog/2020/07/27/recursion-on-cartesian-tree/"] 11 | --- 12 | 13 | # 列を最小値で分割して再帰する (名称募集中) 14 | -------------------------------------------------------------------------------- /_tenkeis/modosu-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 戻す DP とは、DP の遷移の逆演算を用いる DP のこと。DP の高速化手法のひとつ。あるいは、実装方法に基づいた DP の分類のひとつ。 9 | draft: true 10 | draft_urls: ["http://sigma425.hatenablog.com/entry/2015/07/31/121439"] 11 | --- 12 | 13 | # 戻す DP 14 | 15 | TODO: セグメント木を用いて両側からやるタイプはこれ? それとも別? 16 | 17 | ## 例題 18 | 19 | - [AtCoder Regular Contest 028: D. 注文の多い高橋商店](https://atcoder.jp/contests/arc028/tasks/arc028_4)[archive.org](https://web.archive.org/web/20210123190024/https://atcoder.jp/contests/arc028/tasks/arc028_4) 20 | - [AtCoder Beginner Contest 144: F - Fork in the Road](https://atcoder.jp/contests/abc144/tasks/abc144_f)[archive.org](https://web.archive.org/web/20210116210859/https://atcoder.jp/contests/abc144/tasks/abc144_f) 21 | - 影響度を計算して修正をする 22 | -------------------------------------------------------------------------------- /_tenkeis/nijou-ki-dp.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 二乗の木 DP とは、計算量が一見 \(O(N^3)\) に見えるが実は \(O(N^2)\) であるようなある種類の木 DP のこと。実装方法と計算量による DP の分類のひとつ。 9 | draft: true 10 | draft_urls: ["https://web.archive.org/web/20150920041654/https://topcoder.g.hatena.ne.jp/iwiwi/20120428/1335635594", "https://snuke.hatenablog.com/entry/2019/01/15/211812"] 11 | --- 12 | 13 | # 二乗の木 DP 14 | -------------------------------------------------------------------------------- /_tenkeis/product-bunkai.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: $H \times W$ の行列 $A$ を適切に 構成したいとき、長さ $H$ のベクトル $b$ と長さ $W$ のベクトル $c$ を作り、行列 $A$ を $A _ {y, x} = f(b_y, c_x)$ (あるいは $A = b c^T$) として生成するとうまくいくことがある。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 重ね合わせに分解する (名称募集中) 14 | -------------------------------------------------------------------------------- /_tenkeis/separation-of-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 変数分離とは一般には微分方程式を解くための手法であるが、競技プログラミングにおいても類似の手法を用いることが多く見られる。 9 | draft: true 10 | draft_urls: ["https://kimiyuki.net/blog/2020/11/04/separation-of-variables/"] 11 | --- 12 | 13 | # 変数分離 14 | -------------------------------------------------------------------------------- /_tenkeis/snakes.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 平面上の構築問題ではなにかをヘビ状に配置するとうまくいくことが多い。 9 | draft: true 10 | draft_urls: https://kokiymgch.hatenablog.com/entry/2017/12/12/153419 11 | --- 12 | 13 | # ヘビ 14 | -------------------------------------------------------------------------------- /_tenkeis/tanten-renketsu.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: 見出し作成 5 | authors: kimiyuki 6 | reviewers: 7 | date: 2020-01-16T00:00:00+09:00 8 | description: 端点を共有する区間の間に辺を張って、区間を頂点とするグラフを作ると、これはよい性質を持つことがある。 9 | draft: true 10 | draft_urls: [] 11 | --- 12 | 13 | # 端点を共有する区間をつないでできるグラフの連結成分 (名称募集中) 14 | -------------------------------------------------------------------------------- /assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "style" 5 | -------------------------------------------------------------------------------- /assets/img/.gitignore: -------------------------------------------------------------------------------- 1 | # Tikz/PGF 2 | *.aux 3 | *.div 4 | *.log 5 | *.pdf 6 | -------------------------------------------------------------------------------- /assets/img/README.md: -------------------------------------------------------------------------------- 1 | # assets/img 2 | 3 | ## この README.md について 4 | 5 | 後から画像を修正する必要が発生したときのために、画像の編集方法をこのファイルに書いておきましょう。 6 | 7 | 8 | ## virtual-tree-example-in.svg 9 | 10 | Graphviz を使っています。 11 | 以下のようにコンパイルしてください。 12 | 13 | ```console 14 | $ dot -T svg virtual-tree-example-in.dot > virtual-tree-example-in.svg 15 | ``` 16 | 17 | 18 | ## virtual-tree-example-out.svg 19 | 20 | ```console 21 | $ dot -T svg virtual-tree-example-out.dot > virtual-tree-example-out.svg 22 | ``` 23 | -------------------------------------------------------------------------------- /assets/img/virtual-tree-example-in.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [ 3 | bgcolor = transparent, 4 | ] 5 | node [ 6 | shape = circle, 7 | fillcolor = white, 8 | style = filled, 9 | ] 10 | 1 -> 2 11 | 1 -> 3 -> 4 -> 5 -> 6 12 | 5 -> 7 13 | 5 -> 8 -> 9 14 | 4 -> 10 15 | 4 -> 11 16 | 3 -> 12 -> 13 -> 14 17 | 3 -> 15 18 | 7, 9, 11, 13, 14 [ 19 | shape = doublecircle, 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /assets/img/virtual-tree-example-in.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3 32 | 33 | 3 34 | 35 | 36 | 37 | 1->3 38 | 39 | 40 | 41 | 42 | 43 | 4 44 | 45 | 4 46 | 47 | 48 | 49 | 3->4 50 | 51 | 52 | 53 | 54 | 55 | 12 56 | 57 | 12 58 | 59 | 60 | 61 | 3->12 62 | 63 | 64 | 65 | 66 | 67 | 15 68 | 69 | 15 70 | 71 | 72 | 73 | 3->15 74 | 75 | 76 | 77 | 78 | 79 | 5 80 | 81 | 5 82 | 83 | 84 | 85 | 4->5 86 | 87 | 88 | 89 | 90 | 91 | 10 92 | 93 | 10 94 | 95 | 96 | 97 | 4->10 98 | 99 | 100 | 101 | 102 | 103 | 11 104 | 105 | 106 | 11 107 | 108 | 109 | 110 | 4->11 111 | 112 | 113 | 114 | 115 | 116 | 6 117 | 118 | 6 119 | 120 | 121 | 122 | 5->6 123 | 124 | 125 | 126 | 127 | 128 | 7 129 | 130 | 131 | 7 132 | 133 | 134 | 135 | 5->7 136 | 137 | 138 | 139 | 140 | 141 | 8 142 | 143 | 8 144 | 145 | 146 | 147 | 5->8 148 | 149 | 150 | 151 | 152 | 153 | 9 154 | 155 | 156 | 9 157 | 158 | 159 | 160 | 8->9 161 | 162 | 163 | 164 | 165 | 166 | 13 167 | 168 | 169 | 13 170 | 171 | 172 | 173 | 12->13 174 | 175 | 176 | 177 | 178 | 179 | 14 180 | 181 | 182 | 14 183 | 184 | 185 | 186 | 13->14 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /assets/img/virtual-tree-example-out.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [ 3 | bgcolor = transparent, 4 | ] 5 | node [ 6 | shape = circle, 7 | fillcolor = white, 8 | style = filled, 9 | ] 10 | { 11 | edge [ color = transparent ] 12 | 1 -> 2 13 | 1 -> 3 -> 4 -> 5 -> 6 14 | 5 -> 7 15 | 5 -> 8 -> 9 16 | 4 -> 10 17 | 4 -> 11 18 | 3 -> 12 -> 13 -> 14 19 | 3 -> 15 20 | } 21 | 7, 9, 11, 13, 14 [ 22 | shape = doublecircle, 23 | ] 24 | 25 | 1, 2, 6, 8, 10, 12, 15 [ 26 | color = transparent, 27 | fontcolor = transparent, 28 | ] 29 | { 30 | edge [ constraint = false ] 31 | 3 -> 4 -> 5 -> 7 32 | 5 -> 9 33 | 4 -> 11 34 | 3 -> 13 -> 14 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /assets/img/virtual-tree-example-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | %3 11 | 12 | 13 | 1 14 | 15 | 1 16 | 17 | 18 | 19 | 2 20 | 21 | 2 22 | 23 | 24 | 25 | 1->2 26 | 27 | 28 | 29 | 30 | 31 | 3 32 | 33 | 3 34 | 35 | 36 | 37 | 1->3 38 | 39 | 40 | 41 | 42 | 43 | 4 44 | 45 | 4 46 | 47 | 48 | 49 | 3->4 50 | 51 | 52 | 53 | 54 | 55 | 3->4 56 | 57 | 58 | 59 | 60 | 61 | 12 62 | 63 | 12 64 | 65 | 66 | 67 | 3->12 68 | 69 | 70 | 71 | 72 | 73 | 13 74 | 75 | 76 | 13 77 | 78 | 79 | 80 | 3->13 81 | 82 | 83 | 84 | 85 | 86 | 15 87 | 88 | 15 89 | 90 | 91 | 92 | 3->15 93 | 94 | 95 | 96 | 97 | 98 | 5 99 | 100 | 5 101 | 102 | 103 | 104 | 4->5 105 | 106 | 107 | 108 | 109 | 110 | 4->5 111 | 112 | 113 | 114 | 115 | 116 | 10 117 | 118 | 10 119 | 120 | 121 | 122 | 4->10 123 | 124 | 125 | 126 | 127 | 128 | 11 129 | 130 | 131 | 11 132 | 133 | 134 | 135 | 4->11 136 | 137 | 138 | 139 | 140 | 141 | 4->11 142 | 143 | 144 | 145 | 146 | 147 | 6 148 | 149 | 6 150 | 151 | 152 | 153 | 5->6 154 | 155 | 156 | 157 | 158 | 159 | 7 160 | 161 | 162 | 7 163 | 164 | 165 | 166 | 5->7 167 | 168 | 169 | 170 | 171 | 172 | 5->7 173 | 174 | 175 | 176 | 177 | 178 | 8 179 | 180 | 8 181 | 182 | 183 | 184 | 5->8 185 | 186 | 187 | 188 | 189 | 190 | 9 191 | 192 | 193 | 9 194 | 195 | 196 | 197 | 5->9 198 | 199 | 200 | 201 | 202 | 203 | 8->9 204 | 205 | 206 | 207 | 208 | 209 | 12->13 210 | 211 | 212 | 213 | 214 | 215 | 14 216 | 217 | 218 | 14 219 | 220 | 221 | 222 | 13->14 223 | 224 | 225 | 226 | 227 | 228 | 13->14 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | # Kyopro Encyclopedia of Algorithms (ア辞典) 2 | 3 | これは競プロの知見を収集するための査読付きの半共有 wiki である。 4 | アルゴリズムについての説明が中心となっている。なお、データ構造については [scrapbox.io/data-structures](https://scrapbox.io/data-structures/) (通称: デ wiki) を利用するのがよいだろう。 5 | 6 | 個人ブログの記事として情報を書くと属人性が高すぎ、古い記事のメンテのコストが高く、記事が不正確なまま残りやすいという問題があった。一方で誰でも自由に編集できる共有 wiki であると属人性が低すぎ、誰が書いたのかが分かりにくいため適切なクレジットが行なわれず、また記事の正確性も担保されないという問題があった。 7 | そこでこの半共有 wiki は、GitHub 上のプルリクエストとレビュープロセスという管理形態を用いて、これらの問題の解決を目指している。 8 | もし興味があれば [kmyk/algorithm-encyclopedia](https://github.com/kmyk/algorithm-encyclopedia) から編集に参加してほしい。 9 | 10 |
11 | 12 |
13 | {% assign sorted_algorithms = site.algorithms | sort: "title" %} 14 | {% for entry in sorted_algorithms %} 15 | {% unless entry.tenkei %} 16 | {% assign entry_id = entry.url | split: "/" | last | split: "." | first %} 17 |
18 | {% if entry.algorithm.level %} 19 | 20 | {% endif %} 21 | 22 | {% if entry.draft %} 23 | 24 | 25 | {% endif %} 26 | 27 | {% if entry.draft %} 28 | {{ entry.title }} 29 | {% else %} 30 | {{ entry.title }} 31 | {% endif %} 32 | {% assign aliases_size = entry.algorithm.aliases | size %} 33 | {% if aliases_size != 0 %} 34 | ({{ entry.algorithm.aliases | join: "; " }}) 35 | {% endif %} 36 | 37 | {% if entry.draft %} 38 | 39 | {% for url in entry.draft_urls %} {% octicon link-external height:16 %}{% endfor %} 40 | {% octicon link height:16 %} 41 | 42 | {% endif %} 43 |
44 |
45 | {% capture algorithm_data %} 46 | {% if entry.algorithm.input %}
input
{{ entry.algorithm.input }}
{% endif %} 47 | {% if entry.algorithm.pre_condition %}
pre-condition
{{ entry.algorithm.pre_condition }}
{% endif %} 48 | {% if entry.algorithm.output %}
output
{{ entry.algorithm.output }}
{% endif %} 49 | {% if entry.algorithm.post_condition %}
post-condition
{{ entry.algorithm.post_condition }}
{% endif %} 50 | {% if entry.algorithm.condition %}
condition
{{ entry.algorithm.condition }}
{% endif %} 51 | {% if entry.algorithm.time_complexity %}
time complexity
{{ entry.algorithm.time_complexity }}
{% endif %} 52 | {% if entry.algorithm.space_complexity %}
space complexity
{{ entry.algorithm.space_complexity }}
{% endif %} 53 | {% endcapture %} 54 | {% assign stripped_algorithm_data = algorithm_data | strip %} 55 | {% if entry.draft and stripped_algorithm_data != "" %} 56 |
57 | 58 | {{ entry.description }} 59 | 60 |
61 |
62 | {{ algorithm_data }} 63 |
64 |
65 |
66 | {% else %} 67 | {{ entry.description }} 68 | {% endif %} 69 | 70 | {% endunless %} 71 | {% endfor %} 72 |
73 | 74 | 78 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | isort==5.7.0 2 | mypy==0.812 3 | PyYAML>=5,<6 4 | yapf==0.30.0 5 | -------------------------------------------------------------------------------- /scripts/user-ratings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import json 4 | import pathlib 5 | import re 6 | import time 7 | import urllib.request 8 | from logging import DEBUG, basicConfig, getLogger 9 | from typing import * 10 | 11 | logger = getLogger(__name__) 12 | 13 | 14 | def download_rating_value(user: str) -> Optional[int]: 15 | url = 'https://atcoder.jp/users/{}/history/json'.format(user) 16 | time.sleep(1) 17 | logger.info('GET %s', url) 18 | try: 19 | with urllib.request.urlopen(url) as fh: 20 | data = json.load(fh) 21 | except Exception: 22 | logger.exception('failed to load the history json: user = %s', repr(user)) 23 | return None 24 | if not data: 25 | return -1 26 | rating = 0 27 | for row in data: 28 | rating = max(rating, row['NewRating']) 29 | return rating 30 | 31 | 32 | def get_rating_color_from_value(rating: int) -> str: 33 | if rating < 0: 34 | return 'black' 35 | elif rating < 400: 36 | return 'grey' 37 | elif rating < 800: 38 | return 'brown' 39 | elif rating < 1200: 40 | return 'green' 41 | elif rating < 1600: 42 | return 'cyan' 43 | elif rating < 2000: 44 | return 'blue' 45 | elif rating < 2400: 46 | return 'yellow' 47 | elif rating < 2800: 48 | return 'orange' 49 | else: 50 | return 'red' 51 | 52 | 53 | def collect_users(*, basedir: pathlib.Path) -> List[str]: 54 | users: List[str] = [] 55 | for path in basedir.glob('**/*.md'): 56 | if path.name == 'template.md': 57 | continue 58 | with open(path) as fh: 59 | for line in fh.readlines(): 60 | if line.lstrip().startswith('authors:'): 61 | users.extend(re.findall(r'\w+', line)[1:]) 62 | if line.lstrip().startswith('reviewers:'): 63 | users.extend(re.findall(r'\w+', line)[1:]) 64 | users.extend(re.findall(r'(\w+)', line)) 65 | return sorted(set(users)) 66 | 67 | 68 | def main() -> None: 69 | parser = argparse.ArgumentParser() 70 | parser.add_argument('--input', type=pathlib.Path, default=pathlib.Path.cwd()) 71 | parser.add_argument('--output', type=pathlib.Path, default=pathlib.Path('_sass', 'user-colors.scss')) 72 | args = parser.parse_args() 73 | basicConfig(level=DEBUG) 74 | 75 | lines = [] 76 | lines.append('// THIS FILE IS GENERATED BY user-ratings.py! DO NOT EDIT!') 77 | lines.append('@import "rating-colors";') 78 | lines.append('.handle { font-weight: bold; }') 79 | users = collect_users(basedir=args.input) 80 | for user in users: 81 | rating = download_rating_value(user) 82 | if rating is None: 83 | continue 84 | color = get_rating_color_from_value(rating) 85 | logger.info('user-%s -> %s', user, color) 86 | lines.append('.user-{} {{ color: $rating-color-{}; }}'.format(user, color)) 87 | with open(args.output, 'w') as fh: 88 | for line in lines: 89 | print(line, file=fh) 90 | 91 | 92 | if __name__ == '__main__': 93 | main() 94 | -------------------------------------------------------------------------------- /template.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: entry 3 | changelog: 4 | - summary: ${ここにページの更新内容を書く。例: "見出し作成", "記事作成"} 5 | authors: ${ここにページを更新した人たちの AtCoder ID を書く} 6 | reviewers: ${ここにページの更新をレビューした人たちの AtCoder ID を書く} 7 | date: ${ここにページを更新した日付を 2021-01-01T00:00:00+09:00 のように書く} 8 | algorithm: 9 | input: 10 | output: 11 | time_complexity: 12 | space_complexity: 13 | aliases: [] 14 | level: ${ここにアルゴリズムの難易度の目安を書く} 15 | description: ${ここにアルゴリズムの概要を書く} 16 | draft: true 17 | draft_urls: [] 18 | --- 19 | 20 | # ${ここにタイトルを書く) 21 | -------------------------------------------------------------------------------- /tenkei/index.md: -------------------------------------------------------------------------------- 1 | # Kyopro Encyclopedia of 典型テク (α版) 2 | 3 | このページでは、通常は「アルゴリズム」とは呼ばれないようなものたちを紹介する。通常のアルゴリズムたちについては [Kyopro Encyclopedia of Algorithms](../) を参照のこと。 4 | 5 |
6 | 7 |
8 | {% assign sorted_tenkeis = site.tenkeis | sort: "title" %} 9 | {% for entry in sorted_tenkeis %} 10 | {% assign entry_id = entry.url | split: "/" | last | split: "." | first %} 11 | {% if entry.draft %} 12 |
13 | 14 | 15 | {{ entry.title }} 16 | 17 | {% for url in entry.draft_urls %} {% octicon link-external height:16 %}{% endfor %} 18 | {% octicon link height:16 %} 19 | 20 |
21 |
{{ entry.description }}
22 | {% else %} 23 |
{{ entry.title }}
24 |
{{ entry.description }}
25 | {% endif %} 26 | {% endfor %} 27 |
28 | 29 | 33 | --------------------------------------------------------------------------------