某疆员工爆料:为了赶进度,天天加班,一年的项目,几个月就赶出来了。结果,项目刚交付,他们就被释放了。。

文摘   2024-11-29 12:04   山西  
最近某疆的一个员工爆料,隔壁项目组为了赶进度,拼命加班,原本一年要做的项目,硬生生在几个月内赶出来了。
问题来了,项目刚交付,所有人都以为能喘口气了,结果,管理层的反应却是:任务完成,大家解散!对,你没听错,项目交付后,整个团队被“释放”了。
说白了,就是利用你完成项目的价值,之后毫不留情地甩掉你们。想想是不是特别心酸?都快成“加班机器”了,最后啥也没捞到,反倒是被“优化”了。
从程序员的角度讲,这种做法真是让人心寒。大家辛辛苦苦干了几个月,换来的却是被“释放”的结局,感觉自己像是被当成工具使用,完了就丢了。
不知道大家怎么看,反正我觉得,这种做法在任何行业都不应该出现!

算法题:最短回文串

聊个挺有意思的话题:最短回文串的算法题。
说到回文串,很多人第一反应可能就是“字符串从前读到后和从后读到前都一样”那种简洁的定义。可是要实现一个“最短回文串”却没有那么容易。想象一下,你给一个字符串,问你如何最小化地在它前面或后面加上一些字符,使得整个字符串变成回文,怎么做才能让这个过程既高效又优雅?

算法思路

首先,我们要搞清楚题目:给定一个字符串,要求通过在它的前面添加最少的字符,使得整个字符串变成回文。最短回文串,意味着你要尽可能少地添加字符。
要想解决这个问题,我的第一反应是直接想用字符串匹配相关的算法。最直接想到的就是 KMP 算法,虽然它最初是用来解决子串匹配的问题,但它的应用原理能帮我们找出字符串中的最长回文前缀,这对于优化我们的添加字符的步骤至关重要。

具体做法

首先,要判断回文串的性质,我们可以反向读取字符串。然后用反向字符串去匹配原字符串的前缀部分,找出最长的回文前缀。这个匹配过程其实可以通过 KMP 算法的部分匹配表(LPS数组)来加速。具体步骤如下:
  1. 构造新字符串:首先将原字符串和反转后的字符串拼接起来,用一个分隔符分隔开。比如,原字符串是 s = "aacecaaa",那么新字符串 new_s = "aacecaaa#aaacecaa"
  2. 计算 LPS(最长前后缀)数组:通过 KMP 算法,我们计算出这个新字符串的 LPS 数组。LPS 数组中的每一个元素表示该位置之前的子串的最大前后缀长度。
  3. 根据 LPS数组判断:LPS 数组的最后一个值就是反向字符串和原字符串能够匹配的最大前缀长度。通过这个信息,我们可以确定原字符串已经是回文的部分,剩下的部分就是需要补充的。
  4. 返回结果:需要补充的部分就是原字符串中未参与回文匹配的后缀部分。通过将这些字符添加到字符串的前面,我们就能得到最短回文串。

Java实现

好,现在来写点代码,看看具体怎么操作:
public class ShortestPalindrome {

    public String shortestPalindrome(String s) {
        // 如果字符串为空或只有一个字符,直接返回
        if (s == null || s.length() <= 1) {
            return s;
        }

        // 反转字符串
        String reversed = new StringBuilder(s).reverse().toString();
        
        // 拼接原字符串和反转字符串,中间加个#分隔,避免重复匹配
        String newString = s + "#" + reversed;
        
        // 计算LPS数组
        int[] lps = buildLPS(newString);
        
        // LPS数组最后一个值即为原字符串和反转字符串的最大匹配长度
        int longestPrefix = lps[lps.length - 1];
        
        // 根据最长回文前缀的长度来确定需要添加的字符
        String suffixToAdd = s.substring(longestPrefix);
        
        // 将反转的后缀添加到原字符串的前面
        return new StringBuilder(suffixToAdd).reverse().toString() + s;
    }

    // 构建LPS数组
    private int[] buildLPS(String s) {
        int[] lps = new int[s.length()];
        int j = 0// 前缀的末尾

        for (int i = 1; i < s.length(); i++) {
            while (j > 0 && s.charAt(i) != s.charAt(j)) {
                j = lps[j - 1];
            }

            if (s.charAt(i) == s.charAt(j)) {
                j++;
            }

            lps[i] = j;
        }

        return lps;
    }

    public static void main(String[] args) {
        ShortestPalindrome solution = new ShortestPalindrome();
        String s = "aacecaaa";
        System.out.println(solution.shortestPalindrome(s));  // 输出 "aaacecaaa"
    }
}

代码解析

  1. 反转字符串:我们先反转原字符串,这样我们就能比较原字符串和反向字符串。
  2. 构建新的字符串:通过将原字符串和反转字符串拼接,间隔符 # 是为了确保我们不会出现字符的重复匹配。
  3. LPS数组的计算:用 KMP 算法计算出最长的回文前缀,即原字符串和反转字符串相匹配的部分。
  4. 生成最短回文串:根据 LPS 数组的最后一个值来确定最短回文串需要添加的字符。然后将这些字符反转并添加到原字符串的前面。
其实,这个题目说白了就是用字符串匹配的技巧来找到回文串的核心部分,然后利用 KMP 算法高效地计算出我们需要添加的字符,避免了暴力解法的超时问题。通过这种方式,时间复杂度优化到 O(n),相较于暴力解法 O(n^2) 的效率要高很多。

-END-


ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学找我领取。

以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言

程序媛山楂
5年+程序媛,专注于AI编程普及。本号主要分享AI编程、Chat账号、Chat教程、Sora教程、Suno AI、Sora账号、Sora提示词、AI换脸、AI绘画等,帮助解决各种AI疑难杂症。
 最新文章