当前位置: 代码网 > it编程>编程语言>Java > Java回文字符串查找和计数实现方式

Java回文字符串查找和计数实现方式

2026年04月09日 Java 我要评论
1. 回文字符串基础知识回文字符串是一系列字符,正着读和反着读都是一样的,如“madam”或“racecar”。在编程中,我们时常需要检测或者处理回文字

1. 回文字符串基础知识

回文字符串是一系列字符,正着读和反着读都是一样的,如“madam”或“racecar”。

在编程中,我们时常需要检测或者处理回文字符串,例如数据验证、dna序列分析等。

1.1 简述回文字符串的定义

回文是指一个字符串忽略标点、大小写和空格,正向和反向都一样。

回文字符串的定义很简单,举例来说:“level”, “deified”, “civic” 和 “radar” 等都是回文字符串。

1.2 回文字符串的性质和应用场景

  • 性质:回文字符串的主要性质是它们是对称的,其第一个字符和最后一个字符相同,第二个字符和倒数第二个字符相同,以此类推。
  • 应用场景:回文字符串的概念在许多领域都有应用,例如文本编辑器中查找回文单词,生物学中查找特定的dna序列,甚至在某些加密算法中也会使用到回文结构。

2. 查找回文子字符串的方法

2.1. 暴力方法

暴力方法是通过检查所有的子字符串,来确定它们是否为回文。以下是使用java语言的代码示例:

public class bruteforcepalindrome {

    public static boolean ispalindrome(string s) {
        for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
            if (s.charat(i) != s.charat(j)) {
                return false;
            }
        }
        return true;
    }

    public static void findpalindromes(string input) {
        int n = input.length();
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j <= n; j++) {
                string substr = input.substring(i, j);
                if (ispalindrome(substr)) {
                    system.out.println(substr);
                }
            }
        }
    }

    public static void main(string[] args) {
        string s = "ababa";
        findpalindromes(s);
    }
}

2.2. 中心扩展算法

中心扩展算法从每个可能的中心开始检查可能的最长回文。

以下是java代码示例:

public class centerexpansionpalindrome {

    public static void findpalindromes(string input) {
        for (int center = 0; center < 2 * input.length() - 1; center++) {
            int left = center / 2;
            int right = left + center % 2;
            while (left >= 0 && right < input.length() && input.charat(left) == input.charat(right)) {
                system.out.println(input.substring(left, right + 1));
                left--;
                right++;
            }
        }
    }

    public static void main(string[] args) {
        string s = "racecar";
        findpalindromes(s);
    }
}

2.3. manacher’s algorithm(马拉车算法)

马拉车算法是一种高效的查找最长回文子字符串的方法。

这里是一个java实现:

public class manacheralgorithm {

    private static string preprocess(string s) {
        stringbuilder sb = new stringbuilder("$#");
        for (int i = 0; i < s.length(); i++) {
            sb.append(s.charat(i));
            sb.append('#');
        }
        sb.append('@');
        return sb.tostring();
    }

    public static void findpalindromes(string input) {
        string t = preprocess(input);
        int n = t.length();
        int[] p = new int[n];
        int c = 0, r = 0;
        for (int i = 1; i < n - 1; i++) {
            int i_mirror = 2 * c - i;
            p[i] = (r > i) ? math.min(r - i, p[i_mirror]) : 0;
            while (t.charat(i + 1 + p[i]) == t.charat(i - 1 - p[i])) {
                p[i]++;
            }
            if (i + p[i] > r) {
                c = i;
                r = i + p[i];
            }
        }
        for (int i = 1; i < n - 1; i++) {
            if(p[i] > 0) {
                system.out.println(input.substring((i - 1 - p[i]) / 2, (i - 1 + p[i]) / 2));
            }
        }
    }

    public static void main(string[] args) {
        string s = "abababa";
        findpalindromes(s);
    }
}

在上述实现中,先对原始字符串进行预处理,在每个字符间插入特殊符号(比如#),这样可以统一处理偶数长度和奇数长度的回文。然后使用manacheralgorithm中的findpalindromes方法寻找回文子字符串。

3. 统计回文子字符串出现次数

3.1. 哈希表的使用

在找到所有回文子字符串后,我们需要统计它们的出现次数。要有效地做到这一点,我们可以使用哈希表(在java中通常是hashmap)来存储每个子字符串及其对应的计数。

下面的java代码示例展示了如何使用哈希表来统计回文子字符串的次数。

import java.util.hashmap;
import java.util.map;

public class palindromefrequency {

    public static map<string, integer> countpalindromes(string[] palindromes) {
        map<string, integer> palindromecount = new hashmap<>();
        for (string palindrome : palindromes) {
            palindromecount.put(palindrome, palindromecount.getordefault(palindrome, 0) + 1);
        }
        return palindromecount;
    }

    // 假设我们已经有了一个回文子字符串数组
    public static void main(string[] args) {
        string[] palindromes = {"aba", "level", "ana", "level"};
        map<string, integer> count = countpalindromes(palindromes);
        for (string key : count.keyset()) {
            system.out.println("palindrome: " + key + ", count: " + count.get(key));
        }
    }
}

3.2. 结果去重和统计实现

为了去除重复的回文子字符串,我们可以在将字符串加入哈希表之前,先检查它是否已经存在。此外,我们也可能需要对回文字符串按照一定的规则(如字母表顺序)进行排序,以便更好地组织和查询。

以下代码示例展示了如果同时考虑去重和统计:

import java.util.treemap;

public class palindromefrequencyanddeduplication {

    public static treemap<string, integer> countpalindromes(string input) {
        treemap<string, integer> palindromecount = new treemap<>();
        // 此处省略查找回文子字符串的代码... (可以使用上面讨论的任何算法)
        // 假设我们已经有了一个包含所有回文子字符串的列表
        string[] foundpalindromes = {"aba", "level", "ana", "level"};
        for (string palindrome : foundpalindromes) {
            palindromecount.put(palindrome, palindromecount.getordefault(palindrome, 0) + 1);
        }
        return palindromecount;
    }

    public static void main(string[] args) {
        string s = "abacdclevelanalevel";
        treemap<string, integer> count = countpalindromes(s);
        for (map.entry<string, integer> entry : count.entryset()) {
            system.out.println("palindrome: " + entry.getkey() + ", count: " + entry.getvalue());
        }
    }
}

使用treemap而不是hashmap是因为treemap会根据键自然排序,使得输出更易于阅读和检查。

4. 具体实现

4.1. 纯java实现代码示例

现在来实现一个完整的java类,该类可以一次性查找所有的回文子字符串,并统计每个回文子字符串的出现次数。

import java.util.hashmap;
import java.util.map;

public class palindromefinder {

    private static boolean ispalindrome(string s) {
        for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
            if (s.charat(i) != s.charat(j)) {
                return false;
            }
        }
        return true;
    }

    public static map<string, integer> findallpalindromes(string s) {
        map<string, integer> palindromeoccurrences = new hashmap<>();
        for (int i = 0; i < s.length(); i++) {
            for (int j = i + 1; j <= s.length(); j++) {
                string substr = s.substring(i, j);
                if (ispalindrome(substr)) {
                    palindromeoccurrences.put(substr, palindromeoccurrences.getordefault(substr, 0) + 1);
                }
            }
        }
        return palindromeoccurrences;
    }

    public static void main(string[] args) {
        string s = "abaxabaxabb";
        map<string, integer> palindromes = findallpalindromes(s);
        for (map.entry<string, integer> entry : palindromes.entryset()) {
            system.out.println("palindrome: " + entry.getkey() + ", count: " + entry.getvalue());
        }
    }
}

4.2. 优化方案和性能分析

尽管上述实现可以工作,但在大型字符串上可能会变得非常慢。

优化可以从两个方面进行:

  1. 使用更高效的算法,比如manacher’s algorithm,来找回文子串。
  2. 对记录和统计过程进行优化,比如使用treemap以保持排序,或者其它结构来优化查询和更新操作。

性能方面,我们应该考虑算法的时间复杂度和空间复杂度。原始的暴力搜索算法的时间复杂度是o(n^3),并且我们还需要额外的空间来存储所有的子字符串和计数。优化后的算法,如manacher’s算法,将时间复杂度提高到了o(n),这对于处理长字符串数据来说,提升是非常明显的。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com