题意就是差分后求形如ABA的串的个数,B的长度为M
这是2011国家集训队互测的试题,是道好题,我直接给出出题人的题解吧:
对于这种在线性序列上的组合计数问题,我们很容易想到一个工具:分治!分治算法在形如快速排序等地方能顺利优化算法,我们尝试将其运用至本题中。
不妨设过程F(Left,Right)可以统计在区间[Left,Right]中满足条件的子序列的个数。
设Mid为区间[Left,Right]的中点由于分治执行,我们不需要统计那些属于[Left,Mid],[Mid+1,Right]中的子序列,剩下的我们分两种情况讨论。
1、 点Mid∈Q。这种情况由于|Q|非常小,我们可以直接枚举Q的位置,然后我们可以穷举A部分长度,然后后缀数组+RMQ解决这个问题
此时算法多了一个系数M,不过整体仍然可以在O(NMLogN)的复杂度内完成。
2、 点Mid∉Q,这种情况就比较麻烦了,可以表示成如下示意图:
由于Mid的存在,P2被分割成了3份,由于P1=P2,我们把P1也分割成3份,经过仔细观察,我们发现只需要枚举红线的位置即可解决此部分的统计问题。黄色部分的最大匹配值可以通过将整个Mid左面的部分倒置后求LCP可得。而Mid以及绿色部分的匹配值可以直接通过后缀数组+RMQ求的。知道了绿色与黄色部分的最大值后,那么Q的位置个数也可以相应得出,问题得到解决,此部分复杂度为O(NLogN)。
方法三总复杂度为O(NMLogN),为一个非常优秀的算法。
1 const eps=1e-8; 2 var s,h,sa,rank:array[0..100010,0..1] of longint; 3 sum,a,b,x,y:array[0..100010] of longint; 4 f:array[0..100010,0..20,0..1] of longint; 5 d:array[0..20] of longint; 6 t,mx,ans,i,n,m:longint; 7 8 procedure swap(var a,b:longint); 9 var c:longint; 10 begin 11 c:=a; 12 a:=b; 13 b:=c; 14 end; 15 16 function min(a,b:longint):longint; 17 begin 18 if a>b then exit(b) else exit(a); 19 end; 20 21 procedure suffix(k:longint); 22 var i,j,m,p:longint; 23 begin 24 fillchar(sum,sizeof(sum),0); 25 for i:=1 to n do 26 inc(sum[s[i,k]]); 27 for i:=1 to mx do 28 inc(sum[i],sum[i-1]); 29 for i:=n downto 1 do 30 begin 31 sa[sum[s[i,k]],k]:=i; 32 dec(sum[s[i,k]]); 33 end; 34 p:=1; 35 rank[sa[1,k],k]:=1; 36 for i:=2 to n do 37 begin 38 if s[sa[i,k],k]<>s[sa[i-1,k],k] then inc(p); 39 rank[sa[i,k],k]:=p; 40 end; 41 m:=p; 42 j:=1; 43 while m<n do 44 begin 45 for i:=1 to n do 46 begin 47 y[i]:=rank[i,k]; 48 sum[i]:=0; 49 end; 50 p:=0; 51 for i:=n-j+1 to n do 52 begin 53 inc(p); 54 x[p]:=i; 55 end; 56 for i:=1 to n do 57 if sa[i,k]>j then 58 begin 59 inc(p); 60 x[p]:=sa[i,k]-j; 61 end; 62 63 for i:=1 to n do 64 begin 65 a[i]:=y[x[i]]; 66 inc(sum[a[i]]); 67 end; 68 for i:=1 to m do 69 inc(sum[i],sum[i-1]); 70 for i:=n downto 1 do 71 begin 72 sa[sum[a[i]],k]:=x[i]; 73 dec(sum[a[i]]); 74 end; 75 p:=1; 76 rank[sa[1,k],k]:=1; 77 for i:=2 to n do 78 begin 79 if (y[sa[i,k]]<>y[sa[i-1,k]]) or (y[sa[i,k]+j]<>y[sa[i-1,k]+j]) then inc(p); 80 rank[sa[i,k],k]:=p; 81 end; 82 m:=p; 83 j:=j shl 1; 84 end; 85 h[1,k]:=0; 86 p:=0; 87 for i:=1 to n do 88 begin 89 if rank[i,k]=1 then continue; 90 j:=sa[rank[i,k]-1,k]; 91 while (i+p<=n) and (j+p<=n) and (s[i+p,k]=s[j+p,k]) do inc(p); 92 h[rank[i,k],k]:=p; 93 if p>0 then dec(p); 94 end; 95 for i:=1 to n do 96 f[i,0,k]:=h[i,k]; 97 for j:=1 to t do 98 for i:=1 to n do 99 if i+d[j]-1<=n then 100 f[i,j,k]:=min(f[i,j-1,k],f[i+d[j-1],j-1,k]) 101 else break; 102 end; 103 104 function ask(l,r,k:longint):longint; 105 var p:longint; 106 begin 107 if l>r then swap(l,r); 108 inc(l); 109 p:=trunc(ln(r-l+1)/ln(2)+eps); 110 exit(min(f[l,p,k],f[r-d[p]+1,p,k])); 111 end; 112 113 procedure work(l,r:longint); 114 var mid,i,j,x,y:longint; 115 begin 116 if r-l+1<m+2 then exit; 117 mid:=(l+r) shr 1; 118 for i:=mid-m+1 to mid do 119 for j:=i-1 downto l do 120 begin 121 if r-(i+m)+1<i-j then break; 122 if ask(rank[j,0],rank[i+m,0],0)>=i-j then inc(ans); 123 end; 124 125 for i:=l to mid-m-1 do 126 begin 127 x:=min(ask(rank[i,0],rank[mid,0],0),mid-i-m); 128 if (x<1) then continue; 129 y:=ask(rank[n+1-i,1],rank[n+1-mid,1],1); 130 y:=min(y-1,min(i-l,mid-i-m-1)); 131 if y<mid-i-m-x then continue; 132 ans:=ans+min(x,y-(mid-i-m-x)+1); 133 end; 134 for i:=mid+m+1 to r do 135 begin 136 y:=min(i-mid-m,ask(rank[n+1-i,1],rank[n+1-mid,1],1)); 137 if y<1 then continue; 138 x:=ask(rank[i+1,0],rank[mid+1,0],0); 139 x:=min(x,min(r-i,i-mid-m-1)); 140 if x<i-mid-m-y then continue; 141 ans:=ans+min(y,x-(i-mid-m-y)+1); 142 end; 143 work(l,mid-1); 144 work(mid+1,r); 145 end; 146 147 procedure sort(l,r:longint); 148 var i,j,x:longint; 149 begin 150 i:=l; 151 j:=r; 152 x:=a[(l+r) shr 1]; 153 repeat 154 while a[i]<x do inc(i); 155 while x<a[j] do dec(j); 156 if not(i>j) then 157 begin 158 swap(a[i],a[j]); 159 swap(b[i],b[j]); 160 inc(i); 161 dec(j); 162 end; 163 until i>j; 164 if l<j then sort(l,j); 165 if i<r then sort(i,r); 166 end; 167 168 begin 169 readln(n,m); 170 for i:=1 to n do 171 read(a[i]); 172 dec(n); 173 for i:=1 to n do 174 s[i,0]:=a[i+1]-a[i]; 175 176 for i:=1 to n do 177 begin 178 a[i]:=s[i,0]; 179 b[i]:=i; 180 end; 181 sort(1,n); 182 mx:=1; 183 s[b[1],0]:=1; 184 for i:=2 to n do 185 begin 186 if a[i]<>a[i-1] then inc(mx); 187 s[b[i],0]:=mx; 188 end; 189 for i:=1 to n do 190 s[i,1]:=s[n+1-i,0]; 191 t:=trunc(ln(n)/ln(2)+eps); 192 d[0]:=1; 193 for i:=1 to t do 194 d[i]:=d[i-1]*2; 195 suffix(0); 196 suffix(1); 197 work(1,n); 198 writeln(ans); 199 end.