<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>构造 on Weiuou的博客</title><link>https://blog.weiuou.top/tags/%E6%9E%84%E9%80%A0/</link><description>Recent content in 构造 on Weiuou的博客</description><image><title>Weiuou的博客</title><url>https://blog.weiuou.top/avatar.png</url><link>https://blog.weiuou.top/avatar.png</link></image><generator>Hugo</generator><language>zh-cn</language><copyright>Weiuou</copyright><lastBuildDate>Sat, 01 Aug 2026 15:00:00 +0800</lastBuildDate><atom:link href="https://blog.weiuou.top/tags/%E6%9E%84%E9%80%A0/index.xml" rel="self" type="application/rss+xml"/><item><title>力扣双周赛 187 题解：字符串构造、峰值公式、逆序对与区间 DP</title><link>https://blog.weiuou.top/posts/leetcode-biweekly-contest-187-editorial/</link><pubDate>Sat, 01 Aug 2026 15:00:00 +0800</pubDate><guid>https://blog.weiuou.top/posts/leetcode-biweekly-contest-187-editorial/</guid><description>LeetCode 第 187 场双周赛四题完整中文题解，涵盖字符串分桶构造、严格交替序列峰值公式、三类别逆序对和不重叠区间 DP，附 Java 17 标程、正确性证明、复杂度分析与完整视频讲解。</description><content:encoded><![CDATA[<h2 id="完整视频讲解">完整视频讲解</h2>
<p>🎬 <a href="https://www.bilibili.com/video/BV1EvG36wE9v">前往 Bilibili 观看《力扣双周赛 187 四题完整题解》</a></p>
<p>视频章节：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">00:00 3992 - 重新排列字符串以避免字符对
</span></span><span class="line"><span class="cl">02:02 3993 - 交替数列的最大元素
</span></span><span class="line"><span class="cl">04:01 3994 - 划分数组的最少相邻交换次数
</span></span><span class="line"><span class="cl">06:05 3995 - 转换字符串的最小成本 III
</span></span></code></pre></div><p>本文整理第 187 场力扣双周赛的四道题。四份 Java 17 代码均经过本地编译、官方样例、边界用例与差分测试；本次采用本地模式，没有向力扣账号提交代码，因此不把本地验证写成平台 <code>Accepted</code>。</p>
<h2 id="题目总览">题目总览</h2>
<table>
	<thead>
			<tr>
					<th>题号</th>
					<th>题目</th>
					<th>难度</th>
					<th>核心方法</th>
					<th>时间复杂度</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>3992</td>
					<td><a href="https://leetcode.cn/problems/rearrange-string-to-avoid-character-pair/">重新排列字符串以避免字符对</a></td>
					<td>Easy</td>
					<td>三类字符分桶构造</td>
					<td><code>O(n)</code></td>
			</tr>
			<tr>
					<td>3993</td>
					<td><a href="https://leetcode.cn/problems/maximum-value-of-an-alternating-sequence/">交替数列的最大元素</a></td>
					<td>Medium</td>
					<td>峰值上界与构造公式</td>
					<td><code>O(1)</code></td>
			</tr>
			<tr>
					<td>3994</td>
					<td><a href="https://leetcode.cn/problems/minimum-adjacent-swaps-to-partition-array/">划分数组的最少相邻交换次数</a></td>
					<td>Medium</td>
					<td>三类别逆序对计数</td>
					<td><code>O(n)</code></td>
			</tr>
			<tr>
					<td>3995</td>
					<td><a href="https://leetcode.cn/problems/minimum-cost-to-convert-string-iii/">转换字符串的最小成本 III</a></td>
					<td>Hard</td>
					<td>不重叠区间前缀 DP</td>
					<td><code>O(nRL)</code></td>
			</tr>
	</tbody>
</table>
<h2 id="3992-重新排列字符串以避免字符对三类字符分桶">3992. 重新排列字符串以避免字符对｜三类字符分桶</h2>
<p><img alt="3992 字符分桶构造" loading="lazy" src="/images/posts/leetcode-biweekly-contest-187/3992.png"></p>
<h3 id="题意">题意</h3>
<p>给定字符串 <code>s</code> 和两个不同字符 <code>x</code>、<code>y</code>。可以任意重排 <code>s</code>，要求结果中每个 <code>y</code> 都出现在每个 <code>x</code> 之前，返回任意一个满足条件的排列。</p>
<h3 id="核心思路">核心思路</h3>
<p>题目只约束 <code>x</code> 与 <code>y</code> 的相对位置，其他字符放在哪里都不影响合法性。把字符分成三类：</p>
<ul>
<li><code>Y</code>：所有字符 <code>y</code>；</li>
<li><code>M</code>：所有既不是 <code>x</code> 也不是 <code>y</code> 的字符；</li>
<li><code>X</code>：所有字符 <code>x</code>。</li>
</ul>
<p>最直接的合法骨架就是：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Y + M + X
</span></span></code></pre></div><p>代码先统计 <code>x</code>、<code>y</code> 的数量，再选择一个确定性布局：</p>
<ul>
<li><code>countY &lt; countX</code>：输出 <code>Y + M + X</code>；</li>
<li>否则：按原顺序输出所有非 <code>x</code> 字符，再输出全部 <code>x</code>，即 <code>Non-X + X</code>。</li>
</ul>
<p>第二个布局仍然合法，因为 <code>x != y</code>，所以所有 <code>y</code> 都属于前面的 <code>Non-X</code> 部分。</p>
<p>例如 <code>s = &quot;zzayzb&quot;</code>、<code>x = 'z'</code>、<code>y = 'a'</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Y = a
</span></span><span class="line"><span class="cl">M = yb
</span></span><span class="line"><span class="cl">X = zzz
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">answer = aybzzz
</span></span></code></pre></div><h3 id="正确性证明">正确性证明</h3>
<p>分两部分证明。</p>
<p>首先证明结果是原串的排列。第一种分支中，<code>Y</code>、<code>M</code>、<code>X</code> 三类两两不交，并完整覆盖 <code>s</code> 的所有字符；第二种分支中，所有非 <code>x</code> 字符与全部 <code>x</code> 同样两两不交并完整覆盖原串。因此每个输入字符都恰好写入一次。</p>
<p>再证明顺序条件。两种分支都把全部 <code>x</code> 放在最后的后缀。因为 <code>x != y</code>，所有 <code>y</code> 都位于这个后缀之前，所以任意 <code>y</code> 都出现在任意 <code>x</code> 的左侧。故算法返回的字符串一定合法。</p>
<h3 id="复杂度">复杂度</h3>
<ul>
<li>时间复杂度：<code>O(n)</code>；</li>
<li>空间复杂度：<code>O(n)</code>，用于构造返回字符串。</li>
</ul>
<h3 id="java-17-标程">Java 17 标程</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Solution</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="nf">rearrangeString</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">countX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">countY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">length</span><span class="p">();</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">countX</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">countY</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">StringBuilder</span><span class="w"> </span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">StringBuilder</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="na">length</span><span class="p">());</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">countY</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">countX</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">countY</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">answer</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">y</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">length</span><span class="p">();</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">answer</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">length</span><span class="p">();</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">answer</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">c</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">countX</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">answer</span><span class="p">.</span><span class="na">append</span><span class="p">(</span><span class="n">x</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">answer</span><span class="p">.</span><span class="na">toString</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="易错点">易错点</h3>
<ul>
<li>只修复一处 <code>x</code>、<code>y</code> 逆序，不能保证全部 <code>y</code> 都在全部 <code>x</code> 前；</li>
<li>第一种分支的中间段必须同时排除 <code>x</code> 和 <code>y</code>；</li>
<li><code>countY &lt; countX</code> 只是实现选择布局的条件，不是答案存在的条件；</li>
<li><code>x</code> 或 <code>y</code> 没有出现时，约束可能自动成立。</li>
</ul>
<h2 id="3993-交替数列的最大元素峰值上界与构造">3993. 交替数列的最大元素｜峰值上界与构造</h2>
<p><img alt="3993 峰值递推" loading="lazy" src="/images/posts/leetcode-biweekly-contest-187/3993.png"></p>
<h3 id="题意-1">题意</h3>
<p>给定序列长度 <code>n</code>、首项 <code>s</code> 和相邻差绝对值上限 <code>m</code>。要求序列严格上升、严格下降交替出现，求所有合法整数序列中可能出现的最大元素。</p>
<h3 id="核心观察">核心观察</h3>
<p>为了让最大值尽可能大，第一步应当向上：</p>
<ul>
<li>先向上时，第一个峰值最多为 <code>s + m</code>；</li>
<li>先向下时，<code>s</code> 本身就是第一个峰值，不会优于前者。</li>
</ul>
<p>接下来考虑连续两个峰值 <code>H</code>、<code>H'</code>，中间谷值为 <code>V</code>。由于严格下降且元素为整数：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">V &lt;= H - 1
</span></span></code></pre></div><p>下一步最多上升 <code>m</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">H&#39; &lt;= V + m &lt;= H + m - 1
</span></span></code></pre></div><p>所以每经过两步，峰值最多净增 <code>m - 1</code>。</p>
<h3 id="公式">公式</h3>
<p>令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">q = floor(n / 2)
</span></span></code></pre></div><p><code>q</code> 是下标 <code>1, 3, 5, ...</code> 上峰值的数量。第一个峰值是 <code>s + m</code>，后续 <code>q - 1</code> 个峰各增加至多 <code>m - 1</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">answer = s + m + (q - 1)(m - 1)
</span></span><span class="line"><span class="cl">       = s + q(m - 1) + 1
</span></span></code></pre></div><p>当 <code>n = 1</code> 时，序列只有首项，答案为 <code>s</code>。</p>
<p>例如 <code>n = 4, s = 3, m = 5</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">q = 2
</span></span><span class="line"><span class="cl">answer = 3 + 2 × (5 - 1) + 1 = 12
</span></span></code></pre></div><p>可构造序列 <code>3, 8, 7, 12</code> 达到这个值。</p>
<h3 id="正确性证明-1">正确性证明</h3>
<p>上界方面，第一个峰值不超过 <code>s + m</code>；由 <code>H' &lt;= H + m - 1</code>，其后每个峰值相对前一个峰值最多增加 <code>m - 1</code>。因此任何合法序列的最大元素都不超过公式值。</p>
<p>可达性方面，从 <code>s</code> 上升 <code>m</code> 得到第一个峰；之后每次从峰值下降 <code>1</code>，再上升 <code>m</code>。两条相邻边的差分别为 <code>1</code> 和 <code>m</code>，都不超过限制，而且严格下降、严格上升交替成立。每个新峰值恰好增加 <code>m - 1</code>，最终达到公式上界。</p>
<p>上界与构造值相同，因此公式就是答案。</p>
<h3 id="复杂度-1">复杂度</h3>
<ul>
<li>时间复杂度：<code>O(1)</code>；</li>
<li>空间复杂度：<code>O(1)</code>。</li>
</ul>
<h3 id="java-17-标程-1">Java 17 标程</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Solution</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="nf">maximumValue</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">peakCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">2L</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">mavlorenti</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="n">m</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">mavlorenti</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">mavlorenti</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="w"> </span><span class="n">mavlorenti</span><span class="o">[</span><span class="n">1</span><span class="o">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="o">+</span><span class="w"> </span><span class="n">peakCount</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">((</span><span class="kt">long</span><span class="p">)</span><span class="w"> </span><span class="n">mavlorenti</span><span class="o">[</span><span class="n">2</span><span class="o">]</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">1L</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="o">+</span><span class="w"> </span><span class="n">1L</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="易错点-1">易错点</h3>
<ul>
<li>相邻两个峰值的净增上限是 <code>m - 1</code>，不是 <code>m</code>；</li>
<li>第一峰应先向上取得完整的 <code>m</code> 增量；</li>
<li><code>n = 1</code> 要单独处理；</li>
<li><code>n</code> 很大，乘法和返回值必须使用 <code>long</code>。</li>
</ul>
<h2 id="3994-划分数组的最少相邻交换次数三类别逆序对">3994. 划分数组的最少相邻交换次数｜三类别逆序对</h2>
<p><img alt="3994 扫描统计逆序对" loading="lazy" src="/images/posts/leetcode-biweekly-contest-187/3994.png"></p>
<h3 id="题意-2">题意</h3>
<p>通过相邻交换把数组划分成三段：</p>
<ol>
<li>第一段元素全部小于 <code>a</code>；</li>
<li>第二段元素全部位于闭区间 <code>[a,b]</code>；</li>
<li>第三段元素全部大于 <code>b</code>。</li>
</ol>
<p>三段可以为空，求最少相邻交换次数，并对 <code>10^9 + 7</code> 取模。</p>
<h3 id="核心思路-1">核心思路</h3>
<p>具体数值只决定所属区间，可以压缩成三个类别：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">value &lt; a       → 0
</span></span><span class="line"><span class="cl">a &lt;= value &lt;= b → 1
</span></span><span class="line"><span class="cl">value &gt; b       → 2
</span></span></code></pre></div><p>目标数组的类别序列必须形如 <code>0* 1* 2*</code>，也就是非递减序列。将一个序列通过相邻交换排成非递减顺序，最少交换次数恰好等于初始逆序对数量。</p>
<p>类别只有 <code>0、1、2</code>，无需树状数组。扫描前缀时维护：</p>
<ul>
<li><code>middleCount</code>：此前类别 <code>1</code> 的数量；</li>
<li><code>largeCount</code>：此前类别 <code>2</code> 的数量。</li>
</ul>
<p>当前元素的新增贡献为：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">读到 0：middleCount + largeCount
</span></span><span class="line"><span class="cl">读到 1：largeCount
</span></span><span class="line"><span class="cl">读到 2：0
</span></span></code></pre></div><p>例如类别序列 <code>2,1,1,0</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">读 2：+0，累计 0
</span></span><span class="line"><span class="cl">读 1：+1，累计 1
</span></span><span class="line"><span class="cl">读 1：+1，累计 2
</span></span><span class="line"><span class="cl">读 0：+3，累计 5
</span></span></code></pre></div><p>答案为 <code>5</code>。</p>
<h3 id="正确性证明-2">正确性证明</h3>
<p>若 <code>i &lt; j</code> 且类别 <code>c[i] &gt; c[j]</code>，那么最终非递减序列中这两个元素的相对顺序必须颠倒。两个元素只有在某次相邻交换中彼此跨越时才能改变相对顺序，因此每个初始逆序对至少需要一次交换。</p>
<p>反过来，不断交换任意相邻逆序。一次交换恰好消除一个逆序对，不会增加其他逆序；当逆序数降为零时，类别序列已经非递减。因此恰好使用初始逆序对数量的交换就能完成目标。</p>
<p>扫描时，算法对每个元素准确统计所有以它为右端点的新逆序：类别 <code>0</code> 与此前所有 <code>1、2</code> 组成逆序；类别 <code>1</code> 只与此前的 <code>2</code> 组成逆序；类别 <code>2</code> 不会成为逆序右端点。不同右端点对应的逆序集合互不重叠，所以累计值就是全部逆序对数，也就是最少交换次数。</p>
<h3 id="复杂度-2">复杂度</h3>
<ul>
<li>时间复杂度：<code>O(n)</code>；</li>
<li>辅助空间复杂度：<code>O(1)</code>。</li>
</ul>
<h3 id="java-17-标程-2">Java 17 标程</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Solution</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">minAdjacentSwaps</span><span class="p">(</span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">nums</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">final</span><span class="w"> </span><span class="kt">long</span><span class="w"> </span><span class="n">MOD</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1_000_000_007L</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">middleCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">largeCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">long</span><span class="w"> </span><span class="n">swaps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">ferlominta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">nums</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">ferlominta</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">swaps</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">middleCount</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">largeCount</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">swaps</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">largeCount</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">middleCount</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">largeCount</span><span class="o">++</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">swaps</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">MOD</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="易错点-2">易错点</h3>
<ul>
<li><code>value == a</code> 或 <code>value == b</code> 都属于类别 <code>1</code>；</li>
<li>不能只统计相邻错序，答案是所有逆序对数量；</li>
<li>逆序对最多达到 <code>n(n-1)/2</code>，累计必须使用 <code>long</code>；</li>
<li>只在最终答案处取模，类别计数本身不能取模；</li>
<li>模拟实际交换会退化为 <code>O(n²)</code>。</li>
</ul>
<h2 id="3995-转换字符串的最小成本-iii不重叠区间-dp">3995. 转换字符串的最小成本 III｜不重叠区间 DP</h2>
<p><img alt="3995 前缀 DP 路径" loading="lazy" src="/images/posts/leetcode-biweekly-contest-187/3995.png"></p>
<h3 id="题意-3">题意</h3>
<p>给定 <code>source</code>、<code>target</code> 和若干等长规则 <code>pattern -&gt; replacement</code>。<code>pattern</code> 中的 <code>'*'</code> 可以匹配任意字符，实际规则费用等于基础费用加星号数量。一次规则覆盖的位置之后不能再被任何规则使用，求把 <code>source</code> 转成 <code>target</code> 的最小费用；不可行返回 <code>-1</code>。</p>
<h3 id="核心观察-1">核心观察</h3>
<p>“用过的位置不能再次操作”意味着规则不能在同一区间上链式转换。每条规则必须：</p>
<ol>
<li>直接匹配原始 <code>source</code> 的一段连续子串；</li>
<li>一次写出 <code>target</code> 在同一段上的最终内容。</li>
</ol>
<p>于是任意合法方案都等价于从左到右划分字符串：</p>
<ul>
<li><code>source[i] == target[i]</code> 的单个字符可以免费保留；</li>
<li>其他连续区间必须由一条规则直接完成；</li>
<li>所有分段天然互不重叠。</li>
</ul>
<h3 id="状态与转移">状态与转移</h3>
<p>定义：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dp[i] = 完成前缀 [0,i) 的最小费用
</span></span></code></pre></div><p>初始化 <code>dp[0] = 0</code>，其他状态为无穷大。从每个可达位置 <code>i</code> 有两类转移。</p>
<p><strong>免费单字符转移</strong></p>
<p>若 <code>source[i] == target[i]</code>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dp[i+1] = min(dp[i+1], dp[i])
</span></span></code></pre></div><p><strong>规则区间转移</strong></p>
<p>枚举规则 <code>k</code>，长度为 <code>len[k]</code>。它可以从 <code>i</code> 使用，当且仅当：</p>
<ul>
<li><code>i + len[k] &lt;= n</code>；</li>
<li><code>pattern[k]</code> 的每个非星号字符匹配 <code>source[i+j]</code>；</li>
<li><code>replacement[k][j] == target[i+j]</code> 对整段成立。</li>
</ul>
<p>此时：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">dp[i+len[k]] = min(dp[i+len[k]], dp[i] + fullCost[k])
</span></span></code></pre></div><p>其中 <code>fullCost[k]</code> 是基础费用加模式中的星号数量。</p>
<h3 id="正确性证明-3">正确性证明</h3>
<p>先从合法操作方案构造 DP 路径。合法方案的操作区间两两不重叠，按起点排序后，从左到右遍历：没有被操作的位置必须满足 <code>source[i] == target[i]</code>，对应免费边；每个操作区间直接匹配原始 <code>source</code>，并写出对应 <code>target</code> 子串，对应一条规则边。这样得到的 DP 路径与原方案费用相同。</p>
<p>再从 DP 路径构造合法方案。免费边只保留两串相等的字符；每条规则边都验证了原始 <code>source</code> 模式和最终 <code>target</code> 替换串。路径从左到右消费首尾相接的区间，因此所有规则区间互不重叠。按路径执行这些规则后，整个字符串恰好变为 <code>target</code>，费用等于路径权重。</p>
<p>合法方案与 DP 路径可以互相转换且保持费用，因此 <code>dp[n]</code> 就是最小费用；若 <code>dp[n]</code> 不可达，则不存在合法转换方案。</p>
<h3 id="复杂度-3">复杂度</h3>
<p>设字符串长度为 <code>n</code>，规则数量为 <code>R</code>，最大规则长度为 <code>L</code>：</p>
<ul>
<li>时间复杂度：<code>O(nRL)</code>；</li>
<li>空间复杂度：<code>O(n + R)</code>。</li>
</ul>
<h3 id="java-17-标程-3">Java 17 标程</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kd">class</span> <span class="nc">Solution</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="kd">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">minCost</span><span class="p">(</span><span class="n">String</span><span class="w"> </span><span class="n">source</span><span class="p">,</span><span class="w"> </span><span class="n">String</span><span class="w"> </span><span class="n">target</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                       </span><span class="n">java</span><span class="p">.</span><span class="na">util</span><span class="p">.</span><span class="na">List</span><span class="o">&lt;</span><span class="n">java</span><span class="p">.</span><span class="na">util</span><span class="p">.</span><span class="na">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">rules</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">costs</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">source</span><span class="p">.</span><span class="na">length</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">target</span><span class="p">.</span><span class="na">length</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">ruleCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rules</span><span class="p">.</span><span class="na">size</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">patterns</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[</span><span class="n">ruleCount</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">replacements</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">String</span><span class="o">[</span><span class="n">ruleCount</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">lengths</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="o">[</span><span class="n">ruleCount</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">fullCosts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="o">[</span><span class="n">ruleCount</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">ruleCount</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">patterns</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rules</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">k</span><span class="p">).</span><span class="na">get</span><span class="p">(</span><span class="n">0</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">replacements</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rules</span><span class="p">.</span><span class="na">get</span><span class="p">(</span><span class="n">k</span><span class="p">).</span><span class="na">get</span><span class="p">(</span><span class="n">1</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">lengths</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">patterns</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">.</span><span class="na">length</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="kt">int</span><span class="w"> </span><span class="n">wildcardCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">lengths</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">patterns</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">&#39;*&#39;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="o">++</span><span class="n">wildcardCount</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">fullCosts</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">costs</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">wildcardCount</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="n">vornelipta</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Object</span><span class="o">[]</span><span class="w"> </span><span class="p">{</span><span class="n">source</span><span class="p">,</span><span class="w"> </span><span class="n">target</span><span class="p">,</span><span class="w"> </span><span class="n">rules</span><span class="p">,</span><span class="w"> </span><span class="n">costs</span><span class="p">};</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kd">final</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">INF</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">1</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">29</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="kt">int</span><span class="o">[]</span><span class="w"> </span><span class="n">dp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">int</span><span class="o">[</span><span class="n">n</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">INF</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="n">dp</span><span class="o">[</span><span class="n">0</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">INF</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">continue</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">source</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">target</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">min</span><span class="p">(</span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">1</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">ruleCount</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">k</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="kt">int</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">lengths</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="k">continue</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="kt">boolean</span><span class="w"> </span><span class="n">matches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">0</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">len</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="kt">char</span><span class="w"> </span><span class="n">patternChar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">patterns</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">j</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">patternChar</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="sc">&#39;*&#39;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">patternChar</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">source</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">j</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="n">matches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">replacements</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">j</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">target</span><span class="p">.</span><span class="na">charAt</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">j</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="n">matches</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="k">break</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">matches</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">len</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Math</span><span class="p">.</span><span class="na">min</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                        </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">len</span><span class="o">]</span><span class="p">,</span><span class="w"> </span><span class="n">dp</span><span class="o">[</span><span class="n">i</span><span class="o">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fullCosts</span><span class="o">[</span><span class="n">k</span><span class="o">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">dp</span><span class="o">[</span><span class="n">n</span><span class="o">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">INF</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="o">-</span><span class="n">1</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">dp</span><span class="o">[</span><span class="n">n</span><span class="o">]</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><h3 id="易错点-3">易错点</h3>
<ul>
<li>规则不能在同一位置连续施加；</li>
<li>除了检查 <code>pattern</code> 对 <code>source</code> 的匹配，还必须检查 <code>replacement</code> 是否等于目标子串；</li>
<li>两串相同字符可以使用零费用单字符转移；</li>
<li>星号费用按模式中的 <code>'*'</code> 数量计算；</li>
<li>局部选择最便宜或最长规则不保证全局最优，必须使用 DP；</li>
<li><code>source</code> 与 <code>target</code> 长度不同时直接返回 <code>-1</code>。</li>
</ul>
<h2 id="总结">总结</h2>
<p>本场四题可以归纳为四个很有迁移价值的建模动作：</p>
<ol>
<li><strong>只保留真正受约束的相对顺序</strong>：字符串排列题不需要搜索，把字符分桶后直接构造；</li>
<li><strong>研究局部极值之间的净变化</strong>：峰、谷、峰三点给出 <code>m-1</code> 的增长上界，再用同样结构达到上界；</li>
<li><strong>相邻交换排序等价于消除逆序对</strong>：类别很少时，用常数个计数器即可在线统计；</li>
<li><strong>不重叠操作天然对应前缀分段</strong>：把免费位置和规则区间都视作 DP 边，就能统一求最小成本。</li>
</ol>
<p>四题看起来分别属于构造、数学、计数与动态规划，但核心都在于删去无关细节，把题目压缩成最小状态。比记住具体代码更重要的是识别这种“分桶、局部上界、逆序、前缀分段”的转换。</p>
]]></content:encoded></item></channel></rss>