第一个问题,如何比较新生成的数与原数的大小?
比较相同位数的数的大小,从最高位到最低位一位一位比较,如果每一位数都相等,那么这两个数相等;否则找到第一位不相同的数,比较该数大小,该数大的原数大,该数小的原数小;
那么,我们需要一位一位比较,
那么如果前缀是一样的话我们就可以不去比较直接比较不相同的那一位即可
显然,这是扩展kmp所解决的问题
那么我们将数字转化为字符串处理,len为原数的长度
那么,我们就用扩展kmp中的next数组(程序中的extend_next数组)来进行判断:
1、相等:extend_next[i]>=len
2、新数大于原数:s[extend_next[i]+1]<s[i+extend_next[i]] (找到第一个不相等位)
3、新数小于原数:s[extend_next[i]+1]>s[i+extend_next[i]] (找到第一个不相等位)
注意:如果原串是以一个循环节重复所得,令循环节长度为tt。那么最后的结果全部除以tt即可,所以用kmp求循环节
第一道扩展kmp题,各种边界和下标细节和崩溃 orz,三节课就这样过去了 orz
细节:【1】在while里判断相等时,一定要先保证下标不超过len,然后再进行比较不然各种崩溃(while套if-break)
【2】判断原串是否是循环节重复得到时,用 len mod tt判断,要对tt=0判断是否为0不然会除0→_→
var
t,l,e,g,c,len,tt :longint;
i,j :longint;
s :ansistring;
next,extend_next :array[0..200010] of longint;
procedure kmp;
var
p,l1:longint;
i:longint;
begin
p:=0;l1:=len;
for i:=2 to l1 do
begin
while (p<>0) and (s[i]<>s[p+1]) do p:=next[p];
if s[i]=s[p+1] then
begin
inc(p);
next[i]:=p;
end else next[i]:=0;
end;
end;
procedure get_next;
var
p,a,l,len:longint;
k,j:longint;
begin
len:=length(s);
extend_next[1]:=len;a:=0;
while (a+2<=len) do
if (s[a+1]=s[a+2]) then inc(a) else break;
extend_next[2]:=a;a:=2;
//
for k:=3 to len do
begin
p:=a+extend_next[a]-1;
l:=extend_next[k-a+1];
if (k+l-1<p) then extend_next[k]:=l else
begin
if p-k+1<0 then j:=0 else j:=p-k+1;
while (k+j<=len) and (j+1<=len) do
if (s[k+j]=s[j+1]) then inc(j) else break;
extend_next[k]:=j;
if k+extend_next[k]-1>p then a:=k;
end;
end;
end;
begin
//assign(input,'date.in');reset(input);
//assign(output,'2.out');rewrite(output);
readln(t);
for j:=1 to t do
begin
fillchar(next,sizeof(next),0);
fillchar(extend_next,sizeof(extend_next),0);
readln(s);
len:=length(s);
kmp;
tt:=len-next[len];
if (tt=0) then tt:=4 else
if (len mod tt=0) then tt:=len div tt else tt:=1;
//
s:=s+s;
get_next;
e:=0;l:=0;g:=0;
for i:=1 to len do
begin
if (extend_next[i]>=len) then inc(e) else
if (s[extend_next[i]+1]>s[i+extend_next[i]]) then inc(l) else
if (s[extend_next[i]+1]<s[i+extend_next[i]]) then inc(g);
end;
//
writeln('Case ',j,':',' ',l div tt,' ',e div tt,' ',g div tt);
end;
//close(input);close(output);
end.
——by Eirlys
转载请注明出处=w=