上一篇文章 重复字符串的判定问题(kmp 算法) 给出了基于 kmp 算法的字符串重复判定思路,
但是在使用这个算法判定一个长度为 1024*1024*1024 的字符串是否重复时(编译为 32 位程序),内存爆掉了,这提示了该算法很占用内存。
是的,字符串全部加载到内存里面需要一份内存,t1 数组需要四倍于它的内存(int 数组,长度与串一致)。那么,空间上可以优化吗 ?答案是可以的,在那篇剖析 kmp 算法的文章中实际上已经点明了它的本质: t1 数组记录的是每个子串前后缀匹配的长度,在计算子串 [0, n) 的这个值时,其实已经不用保存前面 n-2 个子串的 t1 值了。所以按如下改进后的算法优化空间复杂度。
算法:另外一种省空间的方法去求 T1 数组最后一个元素
/*
设当前针对[0,x] 求得的最长前后缀相等的长度为 t,有以下规则
a). 字符区间相等关系: [0,t-1]=[x-t+1,x], [0,2t-x-2]=[x-t+1,t-1], [0,3t-2x-1]=[x-t+1,2t-x]……
b). 以上各区间 t, 2t-x-1, 3t-2x-2, …. 项数依次少 x-t+1
c). 字符相等关系: [x]=[x-(x-t+1)]=[x-2(x-t+1)]=……=[x-n(x-t+1)]
1.x=0 时 t=0
2.
置 fnd=0
do
— 若 t=0, 则 t=([x]==[0]), fnd=1
— 若 t!=0
— 若 [t]==[x] 则 t=t+1, fnd=1
— 若 2t>x-1 且 [2t-x-1]==[x] 则 t=2t-x-1, fnd=1
— 若 3t>2x-2 且 [3t-2x-2]== [x] 则 t=3t-2x-2, fnd=1
— …
— 若 fnd=1 则 t=([x]==[0]), fnd=1
end