下面对有用到的概念和符号进行声明:
最小表示法:将一个周期已知的周期循环字符串,以字典序最小的周期进行表示的方法。
最小周期:字典序最小的那个周期,用大写字母M表示
T:代表周期
循环字符串:即S[i+T]=S[i]
设S是一循环字符串
(大家不要把中括号和小括号看混了,两个代表的意义不一样)
S(i):代表S中以下标i为开始的一个周期。比如S=0123456,则S(0)=0123456,S(1)=1234560,S(2)=2345601,S(3)=3456012,以此类推
S(i)>S(j):代表S(i)的字典序大于S(j)
S(i)=S(j):代表S(i)于S(j)的字典序相等,即完全匹配。
同构字符串:设W,U同构,则存在常数r,使得对应任意的i>=0,有W[i+r]=U[i],即W(r)=U(0)称为W,U间的相位差
例如:W(0)=111222,U (0)=112221,有W(1)=U(0)。
性质1:假设W,U两个串是同构循环字符串
充要条件是存在0 <=p,q<T ,使得W(p)=U(q)=M
否则,W,U不同构。
性质2,若有W[i]=U[j],W[i+1]=U[j+1],……w[i+k-1]=U[j+k-1]且W[i+k]<U[j+k]
则有 W(i+x)<U(j+x)(x=0,1,2,……k-1,k)
例如
W=221112,U =112221
有W[0]=U[2]
W[1]=U[3]
且W[2]<U[4]
所以W(0)=221112<U(2)=222111
W(1)=211122<U(3)=221112
W(2)=11122<U(4)=211122
这里可以得出重要的性质,因为若W,U是同构的则W的表示在U中也是存在的。即存在r使得W(0)=U(r)
则有
U(r)<U(2)
U(r+1)<U(3)
U(r+2)<U(4)
所以U(2),U(3),U(4),都不可能是最小表示,我们可以直接跳到U(5),继续匹配
一,用最小表示法匹配同构字符串的原理
首先我们先来模拟一下暴力匹配
假设i<=p,j<=q。W,U是互相同构的周期字符串
W(i),U(j)的匹配结果:
1.当匹配到k时失败
若W[i+k]<U[j+k]
说明W(i)<U(j)
这时保持i不变,j++
同理若W[i+k]>U[j+k]
说明W(i)>U(j)
这时保持j不变,i++
即保持字典序较小的那个不变,
2,当k=T-1时还是成功
说明U(i)=W(i)
即W(i)与U(j)相位差为i-j
即W[x+i-j]=U[x]
若直到i,j>=len也没匹配成功过,说明U,W不同构
这样最坏情况就是,i=p,j=q才匹配成功
因为W(q)和U(p)是最小周期,所以i,j到了p,q无法在继续前进。现在的问题是如果快速的移动i,j,
以往我们移动i,j,的方法是暴力枚举,即匹配失败后我们只移动一格,但是效率实在太低了。
然而如果利于的字典序的话,我们就能让i,j跳起来!,从而在O(n)的时间内完成匹配
下面我们开始做飞机啦
不妨假设W(i),和U(j)在下标k处匹配失败(0<=k<=T-1)且W(i)>U(i)
即
1.W[i+k]>U[j+k]
2.W[i+x]=U[j+x] (x=0,1,2……k-1)
由1,2(即性质2)可得
W(i+x)>U(j+x) (x=0,1,2……k)
说明存在比W(i+x)字典序还小的周期
W(i+x)(x=0,1,2……k)都不是最小周期
所以i+k<q
所以i可以放心的移动到i+k+1
同理当W(i)<U(i)时
j可以放心的移动到j+k+1
这样我们实现在不浪费每次匹配的情况下完成了匹配
即使在结果为i=p,j=q的最坏情况下,也只要匹配p+q+n<3n个字符 。
现在我们得到了新的流程
1.当匹配到k时失败
若W[i+k]<U[j+k]
说明W(i)<U(j)
这时保持i不变,j+=k+1
同理若W[i+k]>U[j+k]
说明W(i)>U(j)
这时保持j不变,i+=k+1
即保持字典序较小的那个不变,
2,当k=T-1时还是成功
说明U(i)=W(i)
即W(i)与U(j)相位差为i-j
即W[x+i-j]=U[x]
若直到i,j>=len也没匹配成功过,说明U,W不同构
//这后面的没写完,不知道啥时候会填坑
二.求最小表示法
求最小表示法的关键在于利用性质2,快速排除字典序较大的周期
设循环字符串S的最小表示为S(q), 0<=q<T
三,其他应用
1.求最小周期长度
2.求最大表示
3.求最大的表示的最大下标