Description
nodgd写了一篇文章,自认为这是一篇好文章。nodgd的文章由?个小写英文字母组成。文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数。nodgd在文章中用了排比、对偶、前后照应之类的手法,所以就有很多个子串是相同或者相近的。为了向大家证明这是一篇好文章,nodgd决定给自己的文章进行评分。nodgd首先确定了一个整数?,然后统计出文章中有多少个不相同的长度为?的子串,这个数量就是文章的评分。
然而,nodgd懒得老老实实计算这个评分了,就把任务丢给了你。
然而,nodgd懒得老老实实计算这个评分了,就把任务丢给了你。
Input
第一行包含两个整数?,?,表示文章的长度和需要统计的子串长度。
第二行包含一个长度为?的只包含小写字母的字符串。
第二行包含一个长度为?的只包含小写字母的字符串。
Output
输出一行一个整数,表示文章的评分。
Solutions
将字符串转换为数值,ASCLL值乘上一个素数,在#&*%¥一下,存在hash表里面。
但是会有冲突(不同的串,数值可能小概率的相同),怎么办?
我们可以开两个,三个hash表(乘上不同素数),比较一下,这个概率就会大大减小,就可以AC了。
但是,无论概率多小,总会有错(可能是非酋),有没有不出错的算法。
有!那就是后缀数据结构大家族——后缀平衡树,后缀自动机,后缀数组......
可惜不会啊! /(ㄒoㄒ)/~~
代码
1 const 2 p1=89; 3 mo1=100000007; 4 p2=107; 5 mo2=100000009; 6 var 7 n,m,ans:longint; 8 s:ansistring; 9 a,b,ha,hb,hash_a,hash_b:array [0..200001] of int64; 10 function hash(l,r,tk,k:int64):int64; 11 begin 12 if k=1 then exit(((ha[r]-(ha[l-1]*a[r-l+1]) mod tk)+tk) mod tk); 13 exit(((hb[r]-(hb[l-1]*b[r-l+1]) mod tk)+tk) mod tk); 14 end; 15 16 procedure main; 17 var 18 i:longint; 19 begin 20 a[0]:=1; b[0]:=1; 21 for i:=1 to n do 22 begin 23 ha[i]:=(ha[i-1]*p1+ord(s[i])-96) mod mo1; 24 a[i]:=(a[i-1]*p1) mod mo1; 25 hb[i]:=(hb[i-1]*p2+ord(s[i])-96) mod mo2; 26 b[i]:=(b[i-1]*p2) mod mo2; 27 end; 28 for i:=1 to n-m+1 do 29 begin 30 hash_a[i]:=hash(i,i+m-1,mo1,1); 31 hash_b[i]:=hash(i,i+m-1,mo2,2); 32 end; 33 end; 34 35 procedure qsort(l,r:longint); 36 var 37 t,mid1,mid2:int64; 38 i,j:longint; 39 begin 40 if l>r then exit; 41 i:=l; j:=r; 42 mid1:=hash_a[(l+r) div 2]; 43 mid2:=hash_b[(l+r) div 2]; 44 repeat 45 while (hash_a[i]<mid1) or (hash_a[i]=mid1) and (hash_b[i]<mid2) do inc(i); 46 while (hash_a[j]>mid1) or (hash_a[j]=mid1) and (hash_b[j]>mid2) do dec(j); 47 if i<=j then 48 begin 49 t:=hash_a[i]; hash_a[i]:=hash_a[j]; hash_a[j]:=t; 50 t:=hash_b[i]; hash_b[i]:=hash_b[j]; hash_b[j]:=t; 51 inc(i); dec(j); 52 end; 53 until i>j; 54 qsort(i,r); 55 qsort(l,j); 56 end; 57 58 procedure print; 59 var 60 i:longint; 61 begin 62 ans:=0; 63 for i:=1 to n-m+1 do 64 begin 65 if (hash_a[i]=hash_a[i-1]) and (hash_b[i]=hash_b[i-1]) then 66 continue; 67 inc(ans); 68 end; 69 writeln(ans); 70 end; 71 72 begin 73 assign(input,'article.in'); 74 assign(output,'article.out'); 75 reset(input); 76 rewrite(output); 77 readln(n,m); 78 readln(s); 79 main; 80 qsort(1,n-m+1); 81 print; 82 close(input); 83 close(output); 84 end.