最长正确前缀/后缀算法为啥/如何工作?
Posted
技术标签:
【中文标题】最长正确前缀/后缀算法为啥/如何工作?【英文标题】:Why/how does the Longest Proper Prefix/Suffix algorithm work?最长正确前缀/后缀算法为什么/如何工作? 【发布时间】:2020-07-06 06:41:16 【问题描述】:LPS(Longest Proper Prefix,也是后缀)算法如下:
public static int[] constructLPSArray(String s)
int n = s.length();
int[] arr = new int[n];
int j = 0;
for (int i = 1; i < n; )
if (s.charAt(i) == s.charAt(j))
arr[i] = j + 1;
i++;
j++;
else
if (j != 0)
j = arr[j - 1];
else
i++;
return arr;
if (s.charAt(i) == s.charAt(j))
部分看起来很清晰,但 else
部分不清楚。
我们为什么这样做:
if (j != 0)
j = arr[j - 1];
else
i++;
更具体地说,为什么j = arr[j - 1]
有效?或者我们为什么要这样做?我们如何验证这一步的正确性?
【问题讨论】:
【参考方案1】:假设我们正在解析一个字符数组,其中 i
和 j
的位置如下:
a b a b x x a b a b ...
^ ^
j i
arr
持有:
0 0 1 2 0 0 1 2 3 4
我。例如,该长度的 s 的每个子串的最长前缀/后缀的长度,直到i
。您可能会猜到它是如何从算法的其余部分生成的。现在,如果i
之后的下一个字符与j
之后的下一个字符不匹配,
a b a b x x a b a b a ...
^ ^
j i
我们不必重试匹配,因为我们知道最长的前缀/后缀我们之前的前缀/后缀!查找 arr[j - 1]
得到 2 - 所以我们基本上缓存了此处突出显示的部分的信息
A B a b x x a b A B a ...
=== ^ === ^
j i
完全相同,无需再比较!
【讨论】:
你能解释一下为什么时间复杂度是 O(n) 而不是 n^2 其中 n 是字符串的长度吗?由于 'j' 可能会在某些循环迭代中递减,它似乎可能是 O(n^2) 它是否需要查找“我们之前的前缀/后缀的最长前缀/后缀”,它只为任何 i 递减一次 j?想知道它的复杂性如何是线性的。 @JoeBlack x = # i,j 增加; y = # j 减少; z = # 只有 i 增加了; A = x+y+z = 我们知道 x+z 【参考方案2】: *Here's one more solution*
int length=str.length();
int mid=length/2;
if(length<2)
System.out.println("-1");
for(int i=mid;i>=0;i--)
String prefix=str.substring(0,i);
String suffix=str.substring(length-i,length);
if(suffix.equals("") || prefix.equals(""))
System.out.println("-1");
if(suffix.equals(prefix))
System.out.println(suffix.length());
break;
【讨论】:
以上是关于最长正确前缀/后缀算法为啥/如何工作?的主要内容,如果未能解决你的问题,请参考以下文章