如何有效地确定给定字符串中最长的单个字符回文?
Posted
技术标签:
【中文标题】如何有效地确定给定字符串中最长的单个字符回文?【英文标题】:How do I efficiently determine the longest individual character palindrome in a given string? 【发布时间】:2011-11-20 18:52:50 【问题描述】:给定一个包含字符 [A-Z] 的长度为 N 的字符串,我如何确定单个字符的最长回文?
我会用一个例子来说明这一点:
给定字符串:JOHNOLSON
在分析字符串时,我们发现我们有一个带有字符 O
的回文,使得字符串看起来像 J
O
HN
O
LS
O
N
。 O
的回文长度为 7,基本上看起来像 O
--
O
--
O
强>。另外,请注意有一个带有 N
的回文,但它的长度仅为 6。
另一个例子,
给定字符串:ABCJOHNOLSON
给出与上面相同的结果,长度为 7 的 O
的回文看起来像 O
--
O
--
O
。
然而,对于给定的字符串ABCJOHNOLSONDA
,最长的单个字符回文长度为14,字符A
看起来像A
------------
A
。
其他简单的例子包括:
ABA
--> A
-
A
(长度为3)
ABAXYZ
--> A
-
A
(长度为3)
ABAXYZA
--> A
---
A
(长度为 5),而不是长度为 7,因为 A
-
A
---
A
不是 A
的回文。
请特别注意最后一个示例,因为它说明了问题的细微差别之一。
【问题讨论】:
对于您要查找的内容,必须有一个比“回文”更好的术语,因为您的大多数示例都不是回文。 考虑一个示例字符串ABCDAEEALMNA
,当考虑A
时看起来像A---A--A---A
,这是一个大小为12的回文(当你忽略其余字符的唯一性时) ,但考虑字符串ABCDAEEALMNOA
,其中整个字符串不再是回文,而是一个小得多的子字符串成为最长的回文,即末尾长度为5的A---A
。
我了解您感兴趣的pattern
,它只是不符合术语回文的字典定义。我想知道您正在寻找的是否有正则表达式解决方案。
@BlastFurnace 我明白你在说什么。你会建议用不同的方式来思考这个问题吗?它以回文的形式出现在我面前,所以我不确定它还能被描述为什么。
【参考方案1】:
您可以在线性时间内完成,它在here 中使用代码示例进行了描述。
【讨论】:
【参考方案2】:这是我想出来的,我不知道它的效率如何。
对于字母表中的每个字母, 查找此字母的第一个和最后一个匹配项。 虽然子字符串不是该字母的回文(易于检查), 找到两边的下一个字母,这样每个可能的组合都是 检查。取最长的一个并存放它。 取最长的一个。【讨论】:
当您说在两边找到下一个字母时,您的意思是您当前正在搜索的字符的下一个实例吗?这对于某些字符串会失败,例如“ABAAAACAA” @JordanBentley:不,我的意思是(例如)尝试 0,7 然后 0,6 然后 0,4 然后 0,3 然后 0,2 然后 0,0 然后 2,7 然后 2, 6 然后 2,4 然后 2,3 然后 2,2 然后 3,7 然后 3,6 然后......你明白了:) 但是如果在某些条件下找到回文,你可以打破,立即说。 啊,这更有意义。如果我理解正确,那会起作用,但最坏情况的复杂性将是 O(n!) @JordanBentley:是的,我认为它可能不是那么好。哦,好吧,这是另一种选择:)【参考方案3】:绝对不是最优的。假设输入字符串都是小写的。
using System;
using System.Collections.Generic;
public class LongestPalindrome
public int longest(string s)
Dictionary<char, List<int>> indices =
new Dictionary<char, List<int>>();
// find all indices for each letter
for (int i = 0; i < s.Length; i++)
char c = s[i];
if (!indices.ContainsKey(c))
indices.Add(c, new List<int>());
indices[c].Add(i);
int max = Int32.MinValue;
for (int i = (int)'a'; i <= (int)'z'; i++)
char c = (char)i;
// in case a letter didn't appear at all in the input string
if (!indices.ContainsKey(c)) continue;
List<int> indexList = indices[c];
// in case a letter appeared only once in the input string
if (indexList.Count == 1) max = Math.Max(max, 1);
for (int j = 0; j < indexList.Count; j++)
for (int k = j + 1; k < indexList.Count; k++)
int dist = indexList[k] - indexList[j] + 1;
string sub = s.Substring(indexList[j], dist);
if (isPalendrome(sub, c))
max = Math.Max(max, dist);
return max;
bool isPalendrome(string s, char c)
int i = 0;
while(i < s.Length - 1 - i)
if (s[i] != c && s[s.Length - 1 - i] != c)
i++;
continue;
if (s[i] != s[s.Length - 1 - i]) return false;
i++;
return true;
【讨论】:
以上是关于如何有效地确定给定字符串中最长的单个字符回文?的主要内容,如果未能解决你的问题,请参考以下文章
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢? 输出需要删除的字符个数。