如果输入为“abba”,那么可能的回答是a,b,b,a,bb,abba。
我知道确定弦是否是回文很容易。这就像是:
public static boolean isPalindrome(String str) {
int len = str.length();
for(int i=0; i<len/2; i++) {
if(str.charAt(i)!=str.charAt(len-i-1) {
return false;
}
return true;
}
但找到回文子串的有效方法是什么?
答案 0 :(得分:29)
O(n)
中完成此操作。主要思想是动态编程和(正如其他人已经说过的)计算最大长度的回文以及给定字母中心的组合。
我们真正想要计算的是最长回文的 radius ,而不是长度。
radius 只是length/2
或(length - 1)/2
(对于奇长的回文)。
在给定位置 pr
计算回文半径 i
后,我们使用已计算的半径来查找回文范围[
i - pr ; i
]
。这让我们(因为回文是好的,回文)会跳过范围radiuses
[
i ; i + pr
]
的进一步计算。
我们搜索范围[
i - pr ; i
]
时,每个职位有四种基本情况 i - k
(其中 k
位于 1,2,... pr
):
radius = 0
的i - k
)
(这也意味着 radius = 0
i + k
radius
i + k
与 i - k
相同radius
i + k
减少以适应范围,即因为 {{ 1}} 我们将 i + k + radius > i + pr
缩减为 radius
)pr - k
i + k + radius = i + pr
搜索可能更大的半径完整,详细的解释会很长。一些代码示例怎么样? :)
我找到了波兰老师,JerrWałaszek的这个算法的C ++实现 我已将评论翻译成英文,添加了一些其他评论并简化了一些以便更容易理解主要部分 Take a look here
注意:如果有问题需要了解原因i + k
,请尝试这样:
在某个位置找到 radius (我们称之为 O(n)
)之后,我们需要重新遍历 r
元素,但结果我们可以跳过 r
元素的计算。因此,迭代元素的总数保持不变。
答案 1 :(得分:18)
也许你可以迭代潜在的中间字符(奇数长度的回文)和字符之间的中间点(甚至是长度的回文)并延伸每个字符直到你无法进一步(下一个左右字符不匹配)。
当字符串中没有多个palidromes时,这将节省大量的计算。在这种情况下,稀疏的palidrome串的成本为O(n)。
对于回文密集输入,它将是O(n ^ 2),因为每个位置不能延伸超过阵列/ 2的长度。显然,这更靠近阵列的末端。
public Set<String> palindromes(final String input) {
final Set<String> result = new HashSet<>();
for (int i = 0; i < input.length(); i++) {
// expanding even length palindromes:
expandPalindromes(result,input,i,i+1);
// expanding odd length palindromes:
expandPalindromes(result,input,i,i);
}
return result;
}
public void expandPalindromes(final Set<String> result, final String s, int i, int j) {
while (i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
result.add(s.substring(i,j+1));
i--; j++;
}
}
答案 2 :(得分:9)
所以,每个不同的字母已经是一个回文 - 所以你已经有N + 1个回文,其中N是不同字母的数量(加上空字符串)。你可以在单次运行中做到 - O(N)。
现在,对于非平凡的回文,你可以测试你的弦的每个点是潜在回文的中心 - 在两个方向上生长 - Valentin Ruano 建议。
该解决方案将采用O(N ^ 2),因为每个测试是O(N)和可能的数量&#34;中心&#34;也是O(N) - center
是两个字母之间的字母或空格,同样在Valentin的解决方案中。
注意,基于Manacher's算法,你的问题也有O(N)解决方案(文章描述&#34;最长的回文&#34;,但算法可以用来统计所有这些)< / p>
答案 3 :(得分:6)
我想出了自己的逻辑,这有助于解决这个问题。 快乐的编码..: - )
System.out.println("Finding all palindromes in a given string : ");
subPal("abcacbbbca");
private static void subPal(String str) {
String s1 = "";
int N = str.length(), count = 0;
Set<String> palindromeArray = new HashSet<String>();
System.out.println("Given string : " + str);
System.out.println("******** Ignoring single character as substring palindrome");
for (int i = 2; i <= N; i++) {
for (int j = 0; j <= N; j++) {
int k = i + j - 1;
if (k >= N)
continue;
s1 = str.substring(j, i + j);
if (s1.equals(new StringBuilder(s1).reverse().toString())) {
palindromeArray.add(s1);
}
}
}
System.out.println(palindromeArray);
for (String s : palindromeArray)
System.out.println(s + " - is a palindrome string.");
System.out.println("The no.of substring that are palindrome : "
+ palindromeArray.size());
}
Output:- Finding all palindromes in a given string : Given string : abcacbbbca ******** Ignoring single character as substring palindrome ******** [cac, acbbbca, cbbbc, bb, bcacb, bbb] cac - is a palindrome string. acbbbca - is a palindrome string. cbbbc - is a palindrome string. bb - is a palindrome string. bcacb - is a palindrome string. bbb - is a palindrome string. The no.of substring that are palindrome : 6
答案 4 :(得分:1)
我建议从基础案例中建立并扩展,直到你拥有所有的palindomes。
有两种类型的回文:偶数和奇数。我还没弄明白如何以同样的方式处理两者,所以我会分手。
1)添加所有单个字母
2)使用此列表,您可以获得所有回文的起点。为字符串中的每个索引运行这两个(或1 - &gt; length-1,因为您需要至少2个长度):
findAllEvenFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i) != str.charAt(index+i+1))
return; // Here we found out that this index isn't a center for palindromes of >=i size, so we can give up
outputList.add(str.substring(index-i, index+i+1));
i++;
}
}
//Odd looks about the same, but with a change in the bounds.
findAllOddFrom(int index){
int i=0;
while(true) {
//check if index-i and index+i+1 is within string bounds
if(str.charAt(index-i-1) != str.charAt(index+i+1))
return;
outputList.add(str.substring(index-i-1, index+i+1));
i++;
}
}
我不确定这是否有助于运行时的Big-O,但它应该比尝试每个子字符串更有效。最糟糕的情况是所有相同字母的字符串可能比“查找每个子字符串”计划更糟糕,但是对于大多数输入,它会删除大多数子字符串,因为一旦您意识到它不是一个中心,您就可以停止查看一个子字符串。回文。
答案 5 :(得分:0)
// Maintain an Set of palindromes so that we get distinct elements at the end
// Add each char to set. Also treat that char as middle point and traverse through string to check equality of left and right char
static int palindrome(String str) {
Set<String> distinctPln = new HashSet<String>();
for (int i=0; i<str.length();i++) {
distinctPln.add(String.valueOf(str.charAt(i)));
for (int j=i-1, k=i+1; j>=0 && k<str.length(); j--, k++) {
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(j)))) {
distinctPln.add(str.substring(j,i+1));
}
// String of lenght 2 as palindrome
if ( (new Character(str.charAt(i))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(i,k+1));
}
if ( (new Character(str.charAt(j))).equals(new Character(str.charAt(k)))) {
distinctPln.add(str.substring(j,k+1));
} else {
continue;
}
}
}
Iterator<String> distinctPlnItr = distinctPln.iterator();
while ( distinctPlnItr.hasNext()) {
System.out.print(distinctPlnItr.next()+ ",");
}
return distinctPln.size();
}
答案 6 :(得分:0)
我尝试了以下代码,并且它适用于案例 它也处理单个字符
几乎没有通过的案件:
abaaa --> [aba, aaa, b, a, aa]
geek --> [g, e, ee, k]
abbaca --> [b, c, a, abba, bb, aca]
abaaba -->[aba, b, abaaba, a, baab, aa]
abababa -->[aba, babab, b, a, ababa, abababa, bab]
forgeeksskeegfor --> [f, g, e, ee, s, r, eksske, geeksskeeg,
o, eeksskee, ss, k, kssk]
代码
static Set<String> set = new HashSet<String>();
static String DIV = "|";
public static void main(String[] args) {
String str = "abababa";
String ext = getExtendedString(str);
// will check for even length palindromes
for(int i=2; i<ext.length()-1; i+=2) {
addPalindromes(i, 1, ext);
}
// will check for odd length palindromes including individual characters
for(int i=1; i<=ext.length()-2; i+=2) {
addPalindromes(i, 0, ext);
}
System.out.println(set);
}
/*
* Generates extended string, with dividors applied
* eg: input = abca
* output = |a|b|c|a|
*/
static String getExtendedString(String str) {
StringBuilder builder = new StringBuilder();
builder.append(DIV);
for(int i=0; i< str.length(); i++) {
builder.append(str.charAt(i));
builder.append(DIV);
}
String ext = builder.toString();
return ext;
}
/*
* Recursive matcher
* If match is found for palindrome ie char[mid-offset] = char[mid+ offset]
* Calculate further with offset+=2
*
*
*/
static void addPalindromes(int mid, int offset, String ext) {
// boundary checks
if(mid - offset <0 || mid + offset > ext.length()-1) {
return;
}
if (ext.charAt(mid-offset) == ext.charAt(mid+offset)) {
set.add(ext.substring(mid-offset, mid+offset+1).replace(DIV, ""));
addPalindromes(mid, offset+2, ext);
}
}
希望它很好
答案 7 :(得分:0)
代码是查找回文的所有不同子串。 这是我试过的代码。它工作正常。
import java.util.HashSet;
import java.util.Set;
public class SubstringPalindrome {
public static void main(String[] args) {
String s = "abba";
checkPalindrome(s);
}
public static int checkPalindrome(String s) {
int L = s.length();
int counter =0;
long startTime = System.currentTimeMillis();
Set<String> hs = new HashSet<String>();
// add elements to the hash set
System.out.println("Possible substrings: ");
for (int i = 0; i < L; ++i) {
for (int j = 0; j < (L - i); ++j) {
String subs = s.substring(j, i + j + 1);
counter++;
System.out.println(subs);
if(isPalindrome(subs))
hs.add(subs);
}
}
System.out.println("Total possible substrings are "+counter);
System.out.println("Total palindromic substrings are "+hs.size());
System.out.println("Possible palindromic substrings: "+hs.toString());
long endTime = System.currentTimeMillis();
System.out.println("It took " + (endTime - startTime) + " milliseconds");
return hs.size();
}
public static boolean isPalindrome(String s) {
if(s.length() == 0 || s.length() ==1)
return true;
if(s.charAt(0) == s.charAt(s.length()-1))
return isPalindrome(s.substring(1, s.length()-1));
return false;
}
}
输出:
可能的子串: 一个 b b 一个 AB BB BA ABB BBA ABBA
总可能的子串是10
总回文子串为4
可能的回文子串:[bb,a,b,abba]
花了1毫秒
答案 8 :(得分:0)
function npa($id)
{
$news = Post::where('category_id', $id)->orderBy('created_at', 'desc')->paginate(12);
return view('npa', compact('news'));
}
尝试一下。这是我自己的解决方案。