字符串分析 · 免费

回文与变位词检查器

倒着读一样吗?这两段文本用的字母完全相同吗?两个答案都有,并附上实际参与比较的字符串、它的反转、第一对不一致的字符、藏在其中的最长回文,以及每一侧多出的字母。

在浏览器中检查 · 不上传任何内容
报告问题

回文与变位词工作区

输入框是空的。输入或粘贴一个单词、短语或句子来检查。

回文工作台

倒着读一样吗?

一段文本,四个答案:字符读法、单词读法、其中最长的回文片段,以及需要修改多少个字符。

0 个字符 · 已比较 0 个 · 0 个单词
试一个
视为同一字符

这些选项决定什么算作同一个字符,但绝不会改写你的文本。三个都打开时,你得到的是大家说“回文”时所指的宽松读法,在这种读法下“A man, a plan, a canal: Panama”能通过。三个都关闭则是严格读法,只有字面上完全镜像的文本才算数。数字、符号和 emoji 属于内容,永远不会被去掉。

等待输入
无

在上方输入或粘贴内容,结论就会显示在这里,包括匹配的字符对和第一对不匹配的字符。

比较的字符
0
忽略的字符
0
检测的字符对
0
不匹配的字符对
0
单词
0
不同字符
0
最长片段
无
中间字符
无
镜像

实际比较的内容与它自身的反转

上面一行是应用选项后的文本,下面一行是同一文本的反转。每一列是一对字符。下方带叉号的列表示这对字符不匹配;长度为奇数的文本,其中间字符会带一个菱形,因为它没有配对。

镜像会显示在这里。输入一个短语,或点击上方的差一点,查看一个只差两个字符就能成为回文的句子,这两个字符都会被标出。

另一种读法

按单词的回文

这是另一个问题,有另一个答案。把单词的顺序倒过来,而不是把字符的顺序倒过来,一句话就可能完美地成为自身的镜像,而它的字母却不是。

单词回文至少需要两个单词,因为一个单词倒过来仍然只是一个单词。粘贴一个句子,这种读法就会有自己的结论。

最长片段

文本中最长的回文

用 Manacher 算法找出,它把整段文本扫描一遍,而不是逐一测试每个子串,所以即使粘贴一长串同一个重复字母也依然很快。

一旦有可扫描的内容,最长回文片段就会显示在这里。

字母奇偶性

这些字母能重新排列成回文吗?

这与文本本身是否已经是回文是两个不同的问题,而且简单得多:它只取决于有多少个字符出现了奇数次。

还没有可重新排列的内容。

反转不等于拆分

这里的字符是字素簇,所以带重音的字母、旗帜,以及宇航员 emoji 这样的 ZWJ 序列都会作为一个字符整体反转。如果按码元拆分字符串,emoji 会变成两个损坏的半截,重音也会挪到错误的字母上。

选项改变了问题

只有当大写、空格和标点不再计入时,“A man, a plan, a canal: Panama”才是回文。这是关于问题本身含义的选择,而不是把戏,所以页面会展示它实际比较的字符串,而不只是结论。

变位词是多重集,而不是集合

当两段文本的字符计数完全一致(包括重复)时,它们就互为变位词。所以差异表会统计每个字符多出几个:少一个字母就是全部答案,而知道是哪一个,才能让你改正。

你输入的所有内容都留在这个标签页中。没有词表,没有词典,也没有服务器:答案只是对字符本身的简单算术,这也是为什么页面能告诉你一个字符串是回文,却永远无法告诉你它是不是一个单词。每个输入框最多容纳 20,000 个字符。最长回文片段由 Manacher 算法在与文本长度成正比的时间内找出,所以没有慢速情况,也没有需要退回的上限。你的浏览器支持 Intl.Segmenter,所以字符按字素簇计数和反转:带重音的字母、旗帜和 ZWJ emoji 都各算一个。

工作原理

回文是对规范化字符串的判断,所以页面会把这个字符串展示给你。

几乎所有关于某段文字是不是回文的争论,其实都是在争论什么算作同一个字符。大小写算不算?逗号算不算?Ésope 里的 é 和 reste 里的 e 算不算相同?没有通用答案,所以本页把每个问题都做成一个开关,显示它实际比较的字符序列,再显示这个序列的反转,并标出两者第一次分道扬镳的位置。变位词部分也是同样的思路:它不只给出简单的“是”或“否”,而是展示两张字母频率表和每一侧多出的部分,因为正是这部分告诉你该改什么。

  1. 01

    输入文本,或载入一个示例

    回文问题用一个输入框,变位词问题用两个。不上传也不存储任何内容:整个过程只是在这个标签页里对字符做算术。示例包括著名的巴拿马句子、一个需要忽略变音符号的法语回文、一个按单词对称但按字母不对称的句子,以及一个只差两个字符的“差一点”。

  2. 02

    决定什么算作同一个字符

    大小写、空格和标点、变音符号各有一个开关,因为答案确实取决于它们。三个都打开时,你得到的是大家通常所指的读法:一句话即使带着逗号和大写字母,也可以是回文。三个都关闭时,你得到的是严格读法,只有字面上完全镜像的文本才能通过。页面会注明结论来自哪种读法。

  3. 03

    看推导过程,而不只是结论

    你会看到实际比较的字符串、同一字符串的反转,以及第一对不一致的字符,并分别标出它从开头数和从末尾数的位置。此外还有:需要修改多少个字符、文本中藏着的最长回文,以及这些字母能否重新排列成回文。

为文字游戏、填字游戏、谜题和随手的好奇心而做

字符读法和单词读法、可诊断的“差一点”,以及按重复次数计算的字母。

两个问题,四个答案

字符回文和单词回文是两个不同的问题,两者都会得到回答。“You can cage a swallow, can’t you, but you can’t swallow a cage, can you?”按单词是完美的回文,按字母则完全不是。页面还会给出文本中最长的回文片段,以及要让整段文本成为自身镜像需要修改的字符数。

可以诊断的“差一点”

单单一个“否”毫无用处。镜像视图把比较的字符串和它自身的反转逐列上下对齐,因此每一对不一致的字符都会在两个位置上被标出。把“Was it a car or a cat I saw?”中的“saw”改成“was”,页面会告诉你它现在差两个字符,以及是哪两个。

反转后依然完好的 Unicode

字符是字素簇,而不是字节。按码元拆分字符串再反转,会把一个 emoji 撕成两个损坏的半截,还会把组合重音符挪到前一个字母上。在这里,带重音的字母、旗帜,以及宇航员这样的 ZWJ 序列都会作为一个字符整体反转,所以 🧑‍🚀 Never odd or even 🧑‍🚀 反转后完好无损。

差异表,而不只是一个“否”

当两段文本不是变位词时,有用的输出是剩下的部分。每一侧都有自己的多余字符列表及其数量,所以“Dormitory”对比“Dirty rooms”不只是失败:它会告诉你第二段文本多了一个 s,删掉它这一对就完全匹配了。

字母奇偶性,第三个问题

一袋字母当且仅当最多只有一个字母出现奇数次时,才能重新排列成回文。页面会对每段文本做这项检查,指出必须放在中间的那个字母,并给出一种可行的排列。这是无需逐个尝试就能知道是否存在这种排列的最快方法。

线性时间,所以没有慢速情况

最长回文片段由 Manacher 算法找出,它只扫描文本一遍。显而易见的做法是从每个可能的中心向外扩展回文,这是二次复杂度,恰好会在本工具鼓励你尝试的输入上卡住:一长串同一个重复字符。这里没有计算量上限,因为根本不需要。

文字游戏问答

巴拿马、tattarrattat、semordnilap,以及为什么反转字符串比看上去更难。

“A man, a plan, a canal: Panama”真的是回文吗?+

按大家通常所指的读法,是的。去掉大写、空格、逗号和冒号,剩下的是 amanaplanacanalpanama,二十一个字母,正读反读完全一样。如果完全按原样比较,它会立刻失败,因为第一个字符是大写 A,最后一个是小写 a。这不是什么值得掩盖的技术细节,而恰恰是本页把大小写、空格和标点做成开关、并展示实际比较的字符串的全部原因。这句话通常被认为出自 Leigh Mercer,他于 1948 年在 Notes and Queries 上发表了它。同一家族中更长的成员包括“Doc, note: I dissent. A fast never prevents a fatness. I diet on cod.”以及 Demetri Martin 那首 224 个单词的回文诗,它们在这里能通过也是同样的原因。

英语中最长的回文是什么?+

这取决于你接受什么算作单词。《牛津英语词典》中最长的是 tattarrattat,十二个字母,由詹姆斯·乔伊斯在《尤利西斯》中创造,用来表示敲门声。化学家会举出 detartrated,十一个字母。普通词典中最长的通常被认为是 redivider,九个字母,rotator、reviver 和 deified 则各有七个字母。在英语之外,纪录更容易打破:芬兰语有 saippuakivikauppias,十九个字母,意思是皂石商贩,而且它是一个真正的复合词,并非生造。整句回文能长得多,实际的限制是耐心而不是语言。把其中任何一个粘贴到输入框里,最长片段面板会替你确认长度,而不是要你相信一份列表。

空格和标点算不算?+

只有你说算才算,而老实说,两种读法都站得住。严格读法把文本当作一串字符,问这串字符是否等于它自身的反转,这意味着空格、逗号和大写字母都和其他字符一样是字符。宽松读法把回文看作字母的属性,把其余部分丢掉,正是这一点让整句长度的回文成为可能。本页默认采用宽松读法,因为人们输入一句话时问的就是这个,而且结论上会写明这一点:只有在忽略标点后才通过的句子,会被标注为按宽松读法通过,而不是被悄悄放行。这个开关从不删除数字、符号和 emoji,因为它们是内容:12321 是回文,也应该被报告为回文。

什么是 semordnilap?+

一个倒过来拼写会变成另一个单词的单词。Stressed 变成 desserts,drawer 变成 reward,diaper 变成 repaid,而这个名称本身就是英文单词 palindromes 倒过来拼。它不是回文,这正是关键:回文正反读都一样,semordnilap 倒过来读是另一个词。本页无法告诉你找到了一个,因为这需要词典,而这里根本没有词表。它能做的是显示反转后的字符串,这是唯一需要计算机的部分。读一读,自己判断。同样的限制也解释了为什么变位词部分比较的是你提供的两段文本,而不是为一段文本搜索变位词:寻找未知的重新排列需要词表,而词表意味着一种语言、一套拼写标准,以及一场关于专有名词的争论。

变位词区分大小写吗?+

按惯例不区分,本页默认忽略大小写正是出于这个原因。没有人会因为 Listen 和 Silent 其中一个以大写字母开头,就说它们不是变位词。关闭大小写开关,它们就不再匹配,你可以在差异表中看到原因:第一段文本多出一个大写 L 和一个小写 s,第二段多出一个大写 S 和一个小写 l,因为对计算机来说,大写 L 和小写 l 是不同的字符。这种视角偶尔正是你想要的,比如检查两个标识符是否使用相同的字符。但大多数时候并非如此,所以默认开启大小写折叠。变音符号也是同样的道理:忽略它们,résumé 就与 resume 匹配;保留它们,é 就是与 e 不同的字母。

什么才算完美变位词?+

当两段文本的字母构成同一个多重集时,它们就互为变位词:相同的字母,每个字母出现相同的次数,只有顺序不同。人们常常忘记多重集这一点。变位词比较的不是出现了哪些字母,而是每个字母出现了多少次,所以这里的差异表统计的是多出的数量,而不只是列出字母。完美变位词,有时也叫真变位词,是指第二段文本确实经过了重新排列,而不是同一段文本又写了一遍;本页会区分这两种结果,而不是对两者都回答“是”。它还会指出没有任何字母重复的特殊情况,比如 Listen 和 Silent,它们是六个不同字母的一种排列。经典例子值得一试:Eleven plus two 和 Twelve plus one 使用同样的十三个字母,表示同一个数;The Morse code 可以重新排列成 Here come dots。

哪些单词可以重新排列成回文?+

有一个一句话就能说清的测试,而且不需要尝试任何排列。一个字母多重集当且仅当最多只有一个字母出现奇数次时,才能排成回文。其他每个字母都必须围绕中心对称成对,而唯一出现奇数次的字母(如果有的话)就放在正中间。所以 carrace 可以,因为它有两个 c、两个 a、两个 r 和一个 e,把 e 放在中间就得到 racecar。Silent 不行,因为它的六个字母各出现一次,而只有一个能占据中心。本页会对你输入的任何内容做这项奇偶检查,在有中间字母时指出它,并给出一种可行的排列,让你可以验证这个结论,而不必盲目相信。

emoji 和带变音符号的字符能正确反转吗?+

在这里可以,而且值得了解为什么这并非理所当然。JavaScript 字符串是 UTF-16 码元序列,所以常见的一行反转写法(把字符串拆成字符再反转数组)会破坏任何不是单个码元的内容。emoji 是一个代理对,反转后变成两个无效的半截。旗帜由两个区域指示符组成,反转后会变成另一面旗帜,或者什么都没有。写成 e 加组合尖音符的 é,反转后重音会附着到现在位于它前面的那个字母上。改为按码点遍历可以解决前两种情况,但解决不了第三种,而且仍会把 🧑‍🚀 这样的 ZWJ 序列拆成一个人、一个不可见的连接符和一枚火箭。本页按字素簇切分,也就是读者会称为字符的单位,所以这四种情况都能完好地往返。试着在输入框里输入 🧑‍🚀 Never odd or even 🧑‍🚀。

它是如何找出我文本中最长的回文的?+

用 Manacher 算法,它能在与文本长度成正比的时间内找出最长回文子串。显而易见的方法是把每个位置都当作可能的中心,只要字符匹配就向外扩展,这在普通文字上没问题,但最坏情况下是二次复杂度:一串一万个相同字母会让每个中心几乎扩展到底。Manacher 的洞见在于,已经完成的扩展会告诉你下一次扩展可以从多远开始,因为你身处其中的回文是一面镜子,它的左半边能预测右半边。这里的实现在字符之间插入分隔符,让偶数长度和奇数长度的片段由同一个循环找出,并且已经在数千个随机字符串上与暴力搜索的结果做过核对。正因如此,页面对这个答案没有长度上限,也没有更慢的后备模式。

我能检查多少文本,有没有内容会离开我的浏览器?+

每个输入框最多容纳 20,000 个字符,大约三千个单词,而且这些内容哪儿也不去。没有上传,没有请求,也没有存储副本:页面上的每个计数都由普通 JavaScript 在这个标签页里算出,这也是为什么页面能说一个字符串是回文,却永远无法说它是不是一个单词。设置这个上限是为了防止粘贴几兆字节的内容时,标签页在拆分字符和绘制的过程中卡死,而不是因为计算本身很昂贵。在上限之内,一切都是线性的:统计字母、比较两张频率表、检验奇偶性、寻找最长回文片段,都只需扫描一遍。如果你需要更长的文本,你想问的几乎肯定是其中的某一句,那就把那一句粘贴进来。

更多专注好用的工具,随时待命。

探索不断扩充的工具合集,涵盖计算、文档、写作和日常工作。

浏览全部工具