<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>字符串 on 一共十七划</title>
		<link>https://noirzh.com/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/</link>
		<description>Recent content in 字符串 on 一共十七划</description>
		<generator>Hugo</generator>
		<language>zh-CN</language>
		
		
		
		
			<lastBuildDate>Tue, 26 Mar 2024 20:12:17 +0800</lastBuildDate>
		
			<atom:link href="https://noirzh.com/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>题解-统计子串中的唯一字符-哈希表&#43;栈，计算贡献</title>
				<link>https://noirzh.com/%E9%A2%98%E8%A7%A3-%E7%BB%9F%E8%AE%A1%E5%AD%90%E4%B8%B2%E4%B8%AD%E7%9A%84%E5%94%AF%E4%B8%80%E5%AD%97%E7%AC%A6-%E5%93%88%E5%B8%8C%E8%A1%A8%E6%A0%88%EF%BC%8C%E8%AE%A1%E7%AE%97%E8%B4%A1%E7%8C%AE/</link>
				<pubDate>Sun, 26 Nov 2023 16:17:28 +0800</pubDate>
				<guid>https://noirzh.com/%E9%A2%98%E8%A7%A3-%E7%BB%9F%E8%AE%A1%E5%AD%90%E4%B8%B2%E4%B8%AD%E7%9A%84%E5%94%AF%E4%B8%80%E5%AD%97%E7%AC%A6-%E5%93%88%E5%B8%8C%E8%A1%A8%E6%A0%88%EF%BC%8C%E8%AE%A1%E7%AE%97%E8%B4%A1%E7%8C%AE/</guid>
				<description>&lt;blockquote&gt;&#xD;&#xA;&lt;p&gt;Problem: &lt;a href=&#34;https://leetcode.cn/problems/count-unique-characters-of-all-substrings-of-a-given-string/description/&#34;&gt;828. 统计子串中的唯一字符&lt;/a&gt;&lt;/p&gt;&#xD;&#xA;&lt;/blockquote&gt;&#xD;&#xA;&lt;h2&gt;思路&lt;/h2&gt;&#xD;&#xA;&lt;ul&gt;&#xD;&#xA;&lt;li&gt;注意到一个唯一字符对数个子串生效，也就是在多个子串中唯一字符是固定的那几个，很容易想到贡献法&lt;/li&gt;&#xD;&#xA;&lt;li&gt;对于子串起点和终点我们设置成$left,right$,任意字符位置为$a_i$序列,让子串生效的范围是$left-right$这个范围内,存在一个字符a,其序列满足&lt;br/&gt;$$a_{i-1}&amp;lt;left&amp;lt;=a_i&amp;lt;=right&amp;lt;a_{i+1}$$,&lt;/li&gt;&#xD;&#xA;&lt;li&gt;同样可以通过枚举起点终点,得知满足这个条件子串的个数为 $(a_i-a_{i-1})*(a_{i+1}-a_{i})$,&lt;/li&gt;&#xD;&#xA;&lt;li&gt;为了计算方便我们将-1和n作为每个字符的两端,既$a_{-1}=-1,a_{n+1}=n$&lt;/li&gt;&#xD;&#xA;&lt;li&gt;该字母在$a_i$上为答案做的贡献就等于子串的数量&lt;/li&gt;&#xD;&#xA;&lt;/ul&gt;&#xD;&#xA;&lt;h2&gt;解题方法&lt;/h2&gt;&#xD;&#xA;&lt;ul&gt;&#xD;&#xA;&lt;li&gt;使用哈希表存储每个字母的位置序列&lt;/li&gt;&#xD;&#xA;&lt;li&gt;为了前后方便我们使用栈来维护具体的字母序列&lt;/li&gt;&#xD;&#xA;&lt;/ul&gt;&#xD;&#xA;&lt;blockquote&gt;&#xD;&#xA;&lt;p&gt;时间复杂度,O(n)&lt;br/&gt;空间复杂度,O(n)&lt;/p&gt;&#xD;&#xA;&lt;/blockquote&gt;&#xD;&#xA;&lt;h2&gt;Code&lt;/h2&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;class Solution:&#xD;&#xA;    def uniqueLetterString(self, s: str) -&amp;gt; int:&#xD;&#xA;        n=len(s) &#xD;&#xA;        hash=[[n] for _ in range(26)] #最右端点&#xD;&#xA;        for i in range(len(s)-1,-1,-1):&#xD;&#xA;            hash[ord(s[i])-ord(&#39;A&#39;)].append(i)&#xD;&#xA;            #小的在顶部,大的在底部&#xD;&#xA;        res=0&#xD;&#xA;        for i in range(26):&#xD;&#xA;            pre=-1&#xD;&#xA;            while len(hash[i])&amp;gt;1:&#xD;&#xA;                index=hash[i].pop()&#xD;&#xA;                back=hash[i][-1]&#xD;&#xA;                res+=(index-pre)*(back-index)&#xD;&#xA;                pre=index&#xD;&#xA;        return res&lt;/code&gt;&lt;/pre&gt;</description>
			</item>
			<item>
				<title>[A=B]攻略-第三章</title>
				<link>https://noirzh.com/a-one-instruction-esolang-chapter-2-2/</link>
				<pubDate>Tue, 24 Oct 2023 23:02:00 +0800</pubDate>
				<guid>https://noirzh.com/a-one-instruction-esolang-chapter-2-2/</guid>
				<description>&lt;h2&gt;前言&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;这个关键字相当于在找到特定的子字符串之后,删去该子字符串,并且将我们指定的新字符串插入到原字符串的开头与结尾&lt;/p&gt;&#xD;&#xA;&lt;p&gt;类似于正则表达式的^与$的应用&lt;/p&gt;&#xD;&#xA;&lt;p&gt;很像是我们在第二章的操作:将字母压之后换成其他字母往后排以使得压缩持续进行&lt;/p&gt;&#xD;&#xA;&lt;h2&gt;3-1 去除&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;相当简单的教程&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;(start)a=&#xD;&#xA;(end)a=&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;3-2 旋转&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;这里只针对前面不是a进行操作,可以保证&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;(start)b=(end)b&#xD;&#xA;(start)c=(end)c&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;3-3 A到B 2&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;开始上难度了,但是其实不难,我们只需要先把所有特定位置的a变成特殊的,然后再处理另一边的特殊的即可&lt;/p&gt;&#xD;&#xA;&lt;p&gt;就像是我们之前做过的一样,此时的代码如下&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;(start)a=x&#xD;&#xA;xa=ax&#xD;&#xA;(end)a=z&#xD;&#xA;az=za&#xD;&#xA;x=b&#xD;&#xA;z=b&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h3&gt;优化&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;我们很容易注意到我们的xa=ax或者之类的操作只是把所有符合要求的串找出来,保证不阻塞生成&lt;/p&gt;&#xD;&#xA;&lt;p&gt;于是我们注意到移到另一边的位置显然更好(指行数更小),更新之后如下&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;(start)a=(end)x&#xD;&#xA;(end)x=(start)b&#xD;&#xA;(end)a=(start)x&#xD;&#xA;(start)x=(end)b&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;3-5 首尾&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;通过上一题我们就知道弄到尾部直接判断即可&lt;/p&gt;&#xD;&#xA;&lt;p&gt;我们唯一要注意的就是判断在前,不然容易出死循环&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ax=(return)true #有任意一个就是真的,能迅速检查到&#xD;&#xA;by=(return)true&#xD;&#xA;cz=(return)true&#xD;&#xA;&lt;p&gt;#以下的操作会1.在有相同的时候把除了最后一个字母之外都换成其他字母插入到后面 2.没有相同的时候所有都插入到后面&#xA;(start)a=(end)x&#xA;(start)b=(end)y&#xA;(start)c=(end)z&#xA;=(return)false&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;&#xA;&lt;h2&gt;3-6 最多 2&lt;/h2&gt;&#xD;&#xA;&lt;h2&gt;思路&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;与之前的类似,但是我们需要保留所有作比较的字母来保证恢复,然后这里其实就可以&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ca=ac&#xD;&#xA;cb=bc&#xD;&#xA;ba=ab&#xD;&#xA;ab=(end)x&#xD;&#xA;cx=(end)y #y代表abc,可随时换成最多的 #剩下ac和bc&#xD;&#xA;#之后我们不用关心y具体是什么,只要二者消耗,剩下的那个做全员回复就行&#xD;&#xA;&lt;p&gt;ac=(end)y&#xA;bc=(end)y&#xA;#做一个穷举&#xA;ax=aa&#xA;cy=cc&#xA;by=bb&#xA;ay=aa&#xA;bx=bb&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;&#xA;&lt;h3&gt;优化&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;发现ax,ay的行为是相同的,bx,by也是,优化以下&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ca=ac&#xD;&#xA;cb=bc&#xD;&#xA;ba=ab&#xD;&#xA;ab=(end)x&#xD;&#xA;cx=(end)y #y代表abc,可随时换成最多的&#xD;&#xA;#acy bcy ay by cy &#xD;&#xA;&lt;p&gt;ac=(end)y&#xA;bc=(end)y&#xA;x=y&#xA;cy=cc&#xA;by=bb&#xA;ay=a&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;&#xA;&lt;h2&gt;3-7回文串&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;判断是不是消除之后全空即可,如3-5的加强版,我们进行全局替换,然后穷举非空情况,但是注意我们不用考虑剩下来的单个字母的情况,因为那种情况也属于回文串&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;cz=&#xD;&#xA;by=&#xD;&#xA;ax=&#xD;&#xA;(start)a=(end)x&#xD;&#xA;(start)b=(end)y&#xD;&#xA;(start)c=(end)z&#xD;&#xA;xy=(return)false&#xD;&#xA;xz=(return)false&#xD;&#xA;yx=(return)false&#xD;&#xA;yz=(return)false&#xD;&#xA;zx=(return)false&#xD;&#xA;zy=(return)false&#xD;&#xA;=(return)true&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h3&gt;挑战优化&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;注意到我们六行代码目的都只是为了判断是否有两个字母及以上存在&lt;/p&gt;</description>
			</item>
			<item>
				<title>[A=B]攻略-第二章</title>
				<link>https://noirzh.com/a-one-instruction-esolang-chapter-2/</link>
				<pubDate>Tue, 03 Oct 2023 21:07:34 +0800</pubDate>
				<guid>https://noirzh.com/a-one-instruction-esolang-chapter-2/</guid>
				<description>&lt;h2&gt;前言&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;我们要好好理解一下a=(return)b干了啥:&lt;/p&gt;&#xD;&#xA;&lt;ol&gt;&#xD;&#xA;&lt;li&gt;找到匹配的字符串a&lt;/li&gt;&#xD;&#xA;&lt;li&gt;将整个我们的字符串变成b&lt;/li&gt;&#xD;&#xA;&lt;li&gt;中断循环,看结果&lt;/li&gt;&#xD;&#xA;&lt;/ol&gt;&#xD;&#xA;&lt;p&gt;换成函数表达就是&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;if a in s:&#xD;&#xA;    s=b&#xD;&#xA;    return s&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;p&gt;之后判题的只能看到你返回的字符串b&lt;/p&gt;&#xD;&#xA;&lt;h2&gt;2.1 你好世界&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;这里给出来了一个提示,在我们用空等的时候&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;=(return)helloworld&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;2.2 AAA&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;我们需要看a的数量,也就是说我们不用管b,c,将二者全消除之后剩下的就是a,再看其是否大于等于3个即可&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;b=&#xD;&#xA;c=&#xD;&#xA;aaa=(return)true&#xD;&#xA;=(return)false &lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;2.3 恰好三个&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;不用管到底是哪个字符,我们只需要验证是不是三个字符即可,所以先把所有字符变成一样的,例如c&lt;/p&gt;&#xD;&#xA;&lt;p&gt;接下来我们要判断的不是&lt;code&gt;ccc=(return)true&lt;/code&gt;,因为字符串&lt;code&gt;cccc&lt;/code&gt;同样包含&lt;code&gt;ccc&lt;/code&gt;,&lt;/p&gt;&#xD;&#xA;&lt;ul&gt;&#xD;&#xA;&lt;li&gt;我们首先就排除掉大于3个字符的,其一定包含四个及以上的字符串&lt;/li&gt;&#xD;&#xA;&lt;li&gt;这时候对只有三个字符的返回true&lt;/li&gt;&#xD;&#xA;&lt;li&gt;剩下的也是false&lt;/li&gt;&#xD;&#xA;&lt;/ul&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;a=c&#xD;&#xA;b=c&#xD;&#xA;cccc=(return)false &#xD;&#xA;ccc=(return)true  &#xD;&#xA;=(return)false&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;2.4 余数&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;这个是return使用的一个示例,所以我们考虑的仍然是只关心字符串长度,不关心内容&lt;/p&gt;&#xD;&#xA;&lt;ol&gt;&#xD;&#xA;&lt;li&gt;将所有都替换成同样的字符&lt;/li&gt;&#xD;&#xA;&lt;li&gt;发现求的事余3,我们只需要每次都将三个字符的串放空,剩下的字符串长度就是总长度余3的结果&lt;/li&gt;&#xD;&#xA;&lt;li&gt;将长度换成数字&lt;/li&gt;&#xD;&#xA;&lt;/ol&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;这个思路在后续也有用&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;a=c&#xD;&#xA;b=c &#xD;&#xA;ccc=           &#xD;&#xA;cc=(return)2&#xD;&#xA;c=(return)1&#xD;&#xA;=(return)0&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;2.5 奇数&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;h4&gt;划分问题&lt;/h4&gt;&#xD;&#xA;&lt;p&gt;终于开始上难度了,但是这个 思想其实不难理解,我们先做一个简单的想法,我如何判断一长串a是否由奇数组成?&lt;/p&gt;&#xD;&#xA;&lt;ol&gt;&#xD;&#xA;&lt;li&gt;考虑到字符串长度为1&amp;lt;=n&amp;lt;=7,很容易知道0,1,3,5,7为可能的长度&lt;/li&gt;&#xD;&#xA;&lt;li&gt;暴力枚举虽好,但是长度有点太大了,我们可以用另一个方法:奇数减去2之后仍然为奇数&lt;/li&gt;&#xD;&#xA;&lt;li&gt;所以我们很容易想到&lt;code&gt;aaa=a&lt;/code&gt;来清理串,为什么不能是&lt;code&gt;aa=&lt;/code&gt;?&lt;/li&gt;&#xD;&#xA;&lt;li&gt;因为这样没有办法确认是刚开始就没有a,还是被偶数a消除掉的&lt;/li&gt;&#xD;&#xA;&lt;li&gt;此时长度0,1,2,只有2表示原串是偶数&lt;/li&gt;&#xD;&#xA;&lt;/ol&gt;&#xD;&#xA;&lt;h4&gt;做法&lt;/h4&gt;&#xD;&#xA;&lt;p&gt;然后我们知道要去做什么了:把三个字符串相同的集中在一起,相当于按顺序再为这三个字符轮流做上述检查操作&lt;/p&gt;&#xD;&#xA;&lt;p&gt;所以需要排序,让相同字符待在一起&lt;/p&gt;&#xD;&#xA;&lt;p&gt;接下来问题就好解决了&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ba=ab&#xD;&#xA;cb=bc&#xD;&#xA;ca=ac&#xD;&#xA;aaa=a&#xD;&#xA;bbb=b&#xD;&#xA;ccc=c&#xD;&#xA;aa=(return)false&#xD;&#xA;bb=(return)false&#xD;&#xA;cc=(return)false&#xD;&#xA;=(return)true&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h3&gt;进阶&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;你肯定要回来看的,如果你看不懂2.6的话&lt;/p&gt;&#xD;&#xA;&lt;p&gt;发现了什么?我们将同样的情况循环了3遍,也就是说,在单独讨论的时候a,b,c其实是等价的,有没有什么办法将它们的等价用代码解释出来?&lt;/p&gt;&#xD;&#xA;&lt;p&gt;一个很有趣的想法是将b,c转换成等价a,最后判断三段a是否都满足奇数&lt;/p&gt;&#xD;&#xA;&lt;p&gt;一点点魔法:设置一个障碍,让所有相邻相同的字母没有障碍,而让不同的字母之间有障碍&lt;/p&gt;&#xD;&#xA;&lt;p&gt;考虑如下代码的运作&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ba=ab&#xD;&#xA;cb=bc&#xD;&#xA;ca=ac&#xD;&#xA;b=xxax&#xD;&#xA;c=xaxx&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;p&gt;这种情况下会发生什么:相邻的b变成了中间隔着3个x的a,不同字母之间隔着2个x&lt;/p&gt;&#xD;&#xA;&lt;p&gt;更加显式地能看到假设 bacacc:&lt;/p&gt;</description>
			</item>
			<item>
				<title>[A=B]攻略-第一章</title>
				<link>https://noirzh.com/a-one-instruction-esolang-chapter-1/</link>
				<pubDate>Sun, 24 Sep 2023 19:34:01 +0800</pubDate>
				<guid>https://noirzh.com/a-one-instruction-esolang-chapter-1/</guid>
				<description>&lt;h2&gt;前言&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;A=B是一个很好的游戏,建议各位去玩,&lt;a href=&#34;https://store.steampowered.com/app/1720850/AB/&#34;&gt;商店链接&lt;/a&gt;&lt;/p&gt;&#xD;&#xA;&lt;p&gt;题目从简单到困难,有的时候梯度很大,争取慢慢把这系列做出来,主要是带题解的&lt;/p&gt;&#xD;&#xA;&lt;p&gt;不是很喜欢魔数写法,所以大概会更新地很慢&lt;/p&gt;&#xD;&#xA;&lt;p&gt;最后,这个游戏真的很有意思&lt;/p&gt;&#xD;&#xA;&lt;h2&gt;1.1 A到B&lt;/h2&gt;&#xD;&#xA;&lt;p&gt;没什么好说的&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;a=b&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;1.2 大写&lt;/h2&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;a=A&#xD;&#xA;b=B&#xD;&#xA;c=C&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;1.3 去重&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;显然我们最后要保留的状态是没有连续字母&lt;/p&gt;&#xD;&#xA;&lt;p&gt;只需要将重复的几个压成一个就行,不过要注意A=B这个语言的特殊性&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;aa=a&#xD;&#xA;bb=b&#xD;&#xA;cc=c&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;1.4 去重 2&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;同理,这个是把连续的a压没,&lt;/p&gt;&#xD;&#xA;&lt;p&gt;这里之所以会有aaa,而不是直接&lt;code&gt;aa=&lt;/code&gt;是因为假如只压缩的可能会剩下来:例如&lt;code&gt;aaa&lt;/code&gt;会被替换成&lt;code&gt;a&lt;/code&gt;&lt;/p&gt;&#xD;&#xA;&lt;p&gt;,我们这么做的本质是将多的字母先压成两个,再把这两个消除掉&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;aaa=aa&#xD;&#xA;aa=&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;h2&gt;1.5 排序&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;研究语言的必经之路,排序,注意到我们现在在做的是替换字符串&lt;/p&gt;&#xD;&#xA;&lt;p&gt;我们的目的是希望各个字母都在其应该在的位置,但我们不知道数组下标,怎么样能达成这两个条件呢?&lt;/p&gt;&#xD;&#xA;&lt;p&gt;我们需要一个只看相邻的排序算法,也就是冒泡算法,实现起来不难,如下&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;看到了吗,本质就是大的向后挪动,这个在单步运行时候看的更清楚&lt;/p&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ba=ab&#xD;&#xA;cb=bc&#xD;&#xA;ca=ac&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&lt;p&gt;这个排序在之后会常用到的,当我们只关心字母数量之类的而不关心其位置的时候&lt;/p&gt;&#xD;&#xA;&lt;h2&gt;1.6 比较&lt;/h2&gt;&#xD;&#xA;&lt;h3&gt;思路&lt;/h3&gt;&#xD;&#xA;&lt;p&gt;比较a和b的多少,还记得去重怎么做的吗?把两个相同的数摁在一起消除&lt;/p&gt;&#xD;&#xA;&lt;p&gt;这个题也一样,我们把两个不同的字母摁在一起消除,剩下的就是多的字母&lt;/p&gt;&#xD;&#xA;&lt;p&gt;值得一提的是压字母存在两个情况&lt;/p&gt;&#xD;&#xA;&lt;h3&gt;代码&lt;/h3&gt;&#xD;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-python&#34;&gt;ab=&#xD;&#xA;ba=&#xD;&#xA;aa=a&#xD;&#xA;bb=b&lt;/code&gt;&lt;/pre&gt;</description>
			</item>
			<item>
				<title>题解-移位字符串分组-哈希表</title>
				<link>https://noirzh.com/posts/%E9%A2%98%E8%A7%A3-%E7%A7%BB%E4%BD%8D%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%88%86%E7%BB%84/</link>
				<pubDate>Tue, 14 Mar 2023 17:11:00 +0800</pubDate>
				<guid>https://noirzh.com/posts/%E9%A2%98%E8%A7%A3-%E7%A7%BB%E4%BD%8D%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%88%86%E7%BB%84/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;Problem: &lt;a href=&#34;https://leetcode.cn/problems/group-shifted-strings/description/&#34;&gt;249. 移位字符串分组&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;!-- toc --&gt;&#xD;&#xA;&lt;h1 id=&#34;思路&#34;&gt;思路&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;类似于凯撒密码的归类方式,我们将所有能通过轮转得到的字符串放在一起,不难想到可以通过暴力来对每一个字符串匹配&lt;/li&gt;&#xA;&lt;li&gt;对于字符串仔细观察可以发现每一个可以归类到一起的字符串的本质是相同的,不只是字符串长度,还有与左右字母之间的差值&lt;/li&gt;&#xA;&lt;li&gt;综上,对于每一类字符串我们只需要将其转化为模板的样子就能判断是否能归类&lt;/li&gt;&#xA;&lt;li&gt;我们的问题就是如何将字符转成一个标准的模板&lt;/li&gt;&#xA;&lt;li&gt;考虑字符之间的相对关系,&#xA;&lt;ul&gt;&#xA;&lt;li&gt;我们设首位为0,后面的每一位对应的是字符串该位与前一位的差&lt;/li&gt;&#xA;&lt;li&gt;如果小于0则加26,来保证模式字符串相等&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;解题方法&#34;&gt;解题方法&lt;/h1&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;对于每一个字符串,计算其相对字符的模板字符串&lt;/li&gt;&#xA;&lt;li&gt;查询哈希表,如果有则插入到相对的答案组中&lt;/li&gt;&#xA;&lt;li&gt;没有就新开一个答案组&lt;/li&gt;&#xA;&lt;li&gt;重复上述操作&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h1 id=&#34;复杂度&#34;&gt;复杂度&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;时间复杂度:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;只遍历一次 $O(mn)$,m为字符串长度&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;空间复杂度:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;运用了哈希表 $O(n)$&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h1 id=&#34;code&#34;&gt;Code&lt;/h1&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Solution&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; groupStrings(vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;amp;&lt;/span&gt; strings) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;res;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        unordered_map&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;string,&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;hash;&lt;span style=&#34;color:#75715e&#34;&gt;//模板字符串及其对应的在答案的行数&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;iter:strings){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            string tmp&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0_&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;iter[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; now;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;i&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;iter.size();i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                now&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;iter[i]&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;a;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (now&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)&lt;span style=&#34;color:#75715e&#34;&gt;//保证模板的一致性&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    now&lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;26&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                tmp&lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt;to_string(now)&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;_&amp;#34;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;iter[i];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (hash.find(tmp)&lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt;hash.end()){&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                res[hash[tmp]].emplace_back(iter);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                hash[tmp]&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;res.size();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                res.emplace_back(vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,iter));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; res;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
			</item>
	</channel>
</rss>
