LeetCode1392 最长快乐前缀
题目
「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。
给你一个字符串 s,请你返回它的 最长快乐前缀。
如果不存在满足题意的前缀,则返回一个空字符串。
举例子:
-
示例 1:
输入:s = “level”
输出:“l” -
示例 2:
输入:s = “ababab”
输出:“abab”。 -
示例 3:
输入:s = “leetcodeleet”
输出:“leet” -
示例 4:
输入:s = “a”
输出:""
解题思路
思想一 暴力解法
毫无疑问用暴力解法可以进行求解,对字符串进行遍历,在第i次时判断字符串前i个字符是否与后i个字符相同,如果相同则是一个快乐前缀,遍历到最后找到最长的快乐前缀即可。
思想二 动态规划思想
思想是定义一个一维数组kmp[],他的大小与字符串大小相同,kmp[i]的值记录了字符串前i+1个字符(因为数组从0开始)组成的字符串的最长快乐前缀,而题目需要的答案即为字符串的前kmp[string.length-1]个字符组成的字符串。
具体讲一下过程:
以这幅图介绍一下第一种情况,当要计算string[5]的kmp值时,发现前五个字符组成的字符串的最长快乐前缀是aba(因为kmp[4]=3),而我们能够发现string[3]恰好等于当前的string[5],也就是字符b,因此kmp[5]就等于kmp[4]+1。
而如果当前字符不能和之前的字符继续构成快乐前缀怎么办呢,例如将第一幅图最后的字符b改成了字符a,在这种情况下,我们就要去寻找之前的字符串的最长快乐子串,而这种情况的中心思想是,这个字符既然不能和之前的最长快乐前缀构成快乐前缀,那么是否可以和之前的最长的快乐前缀的最长快乐前缀构成快乐前缀,具体的话举下面的一个例子:
以下标24及之前的字符构成的字符串的一个快乐前缀是下标20开始的"aabaa",而下一个字符是b,不等于string[5],因此就要寻找"aabaa"的最长快乐前缀。而因为字符串"aabaa"是快乐前缀,因此在原字符串的开头的前五位是“aabaa”,他的最长快乐前缀长度存储在kmp数组中,kmp[4] = 2。下一步需要判断当前字符’b’是否能与"aa"组成快乐前缀,即判断string[25]是否等于string[2](这个2是因为"aa"长度是2),因为"aab"构成了快乐前缀,因此kmp[25]就等于3(’‘aa’'的长度是2,'b’的长度是1)。
用这样的思路就可以构建出来kmp数组,题目也就解出来了。
代码展示
这里只展示动态规划的代码:
public static String longestPrefix(String s) {
if(s.length()==0)
return "";
if(s.length()==1)
return "";
char string[] = s.toCharArray();
int kmp[] = new int[s.length()];
kmp[0] = 0;
for (int i=1;i< kmp.length;i++)
{
if (string[kmp[i-1]]==string[i])
{
kmp[i] = kmp[i-1] + 1;
}
else
{
if(kmp[i-1]==0)
{
if(string[i]==string[0])
kmp[i] = 1;
else
kmp[i] = 0;
continue;
}
int temp = kmp[i-1];
int a = kmp[temp-1];
char b = string[a];
if(b==string[i]&&kmp[i-1]!=0)
{
kmp[i] = a+1;
}
else
{
if(string[i]==string[0])
kmp[i] = 1;
else
kmp[i] = 0;
}
}
}
int index = kmp[string.length-1];
StringBuffer sb = new StringBuffer();
for (int i=0;i<index;i++)
{
sb.append(string[i]);
}
return sb.toString();
}
如果觉得这篇题解有用的话就给我点个赞吧,有什么也可以在评论区交流交流~