很久以前写的,忘补结题报告了
两串相连中间用特殊的分隔符
然后求height,由于要求求公共子串大于等于k的个数,并且只要位置不同即可
因此不难想到在名次上对height分组,一组内的height保证>=k
下面就是在组内统计的问题了
然后还是不难发现,分别在AB串中的后缀i,j,他们能产生2*[LCP(i,j)-k+1]个公共子串
然后那个著名的性质LCP(i,j)=min(h[rank[i]+1]~h[rank[j]]) (令rank[i]<rank[j])
不难想到维护一个单调增的队列,遇到在B串就统计并维护,遇到在A串就维护
然后再反过来做一遍
具体维护单调队列见程序,否则感觉讲不清

  1 type node=record
  2        h,s:longint;
  3      end;
  4 var s,ss:ansistring;
  5     h,sa,sum,y,x,rank:array[0..201000] of longint;
  6     n,m,i,j,loc,p,k,t,f:longint;
  7     q:array[0..2010000] of node;
  8     w,ans:int64;
  9 
 10 begin
 11   readln(k);
 12   while k<>0 do
 13   begin
 14     readln(s);
 15     loc:=length(s)+1;
 16     readln(ss);
 17     s:=s+' '+ss;
 18     n:=length(s);
 19     fillchar(sum,sizeof(sum),0);
 20     for i:=1 to n do
 21     begin
 22       y[i]:=ord(s[i]);
 23       inc(sum[y[i]]);
 24     end;
 25     m:=255;
 26     for i:=2 to m do
 27       inc(sum[i],sum[i-1]);
 28     for i:=n downto 1 do
 29     begin
 30       sa[sum[y[i]]]:=i;
 31       dec(sum[y[i]]);
 32     end;
 33     p:=1;
 34     rank[sa[1]]:=1;
 35     for i:=2 to n do
 36     begin
 37       if y[sa[i]]<>y[sa[i-1]] then inc(p);
 38       rank[sa[i]]:=p;
 39     end;
 40     m:=p;
 41     j:=1;
 42     while m<n do
 43     begin
 44       y:=rank;
 45       fillchar(sum,sizeof(sum),0);
 46       p:=0;
 47       for i:=n-j+1 to n do
 48       begin
 49         inc(p);
 50         x[p]:=i;
 51       end;
 52       for i:=1 to n do
 53         if sa[i]>j then
 54         begin
 55           inc(p);
 56           x[p]:=sa[i]-j;
 57         end;
 58       for i:=1 to n do
 59       begin
 60         rank[i]:=y[x[i]];
 61         inc(sum[rank[i]]);
 62       end;
 63       for i:=2 to m do
 64         inc(sum[i],sum[i-1]);
 65       for i:=n downto 1 do
 66       begin
 67         sa[sum[rank[i]]]:=x[i];
 68         dec(sum[rank[i]]);
 69       end;
 70       p:=1;
 71       rank[sa[1]]:=1;
 72       for i:=2 to n do
 73       begin
 74         if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p);
 75         rank[sa[i]]:=p;
 76       end;
 77       j:=j shl 1;
 78       m:=p;
 79     end;
 80     h[1]:=0;
 81     p:=0;
 82     for i:=1 to n do
 83     begin
 84       if rank[i]=1 then continue;
 85       j:=sa[rank[i]-1];
 86       while s[i+p]=s[j+p] do inc(p);
 87       h[rank[i]]:=p;
 88       if p>0 then dec(p);
 89     end;
 90 
 91     ans:=0;
 92     t:=0;
 93     f:=0;
 94     w:=0;
 95     if sa[1]<loc then
 96     begin
 97       w:=w+h[2]-k+1;
 98       q[t].h:=h[2];
 99       q[t].s:=1;
100       inc(t);
101     end;
102     for i:=2 to n do
103     begin
104       if h[i]>=k then
105       begin
106         if sa[i]<loc then
107         begin
108           p:=1;
109           w:=w+h[i+1]-k+1; //w维护组内到下一个在B中的后缀(LCP-k+1)和
110         end
111         else if sa[i]>loc then
112         begin
113           ans:=ans+w;
114           if i=n then continue;
115           p:=0;  //这里注意,这是B串的后缀,不能和下一个B串后缀形成公共子串
116         end;
117         while (f<t) and (q[t-1].h>=h[i+1]) do //队中height比当前大直接退,因为它的height一定不是LCP
118         begin
119           w:=w-(q[t-1].h-h[i+1])*q[t-1].s;  //s域维护是队列中当前元素到队中前一个元素之间有多少比它height大
120                                  //这里显然之前height比当前大的元素和下一个B串后缀可能的LCP都应当是当前h[i+1]
121           p:=p+q[t-1].s;
122           dec(t);
123         end;
124         if p>0 then
125         begin
126           q[t].h:=h[i+1];
127           q[t].s:=p;
128           inc(t);
129         end;
130       end
131       else begin
132         t:=0;
133         w:=0;
134         f:=0;
135         if sa[i]<loc then
136         begin
137           q[t].h:=h[i+1];
138           q[t].s:=1;
139           w:=h[i+1]-k+1;
140           inc(t);
141         end;
142       end;
143     end;
144 
145     t:=0;
146     f:=0;
147     w:=0;
148     if sa[1]<loc then
149     begin
150       w:=w+h[2]-k+1;
151       q[t].h:=h[2];
152       q[t].s:=1;
153       inc(t);
154     end;
155     for i:=2 to n do
156     begin
157       if h[i]>=k then
158       begin
159         if sa[i]>loc then
160         begin
161           p:=1;
162           w:=w+h[i+1]-k+1;
163         end
164         else if sa[i]<loc then
165         begin
166           ans:=ans+w;
167           if i=n then continue;
168           p:=0;
169         end;
170         while (f<t) and (q[t-1].h>=h[i+1]) do
171         begin
172           w:=w-(q[t-1].h-h[i+1])*q[t-1].s;
173           p:=p+q[t-1].s;
174           dec(t);
175         end;
176         if p>0 then
177         begin
178           q[t].h:=h[i+1];
179           q[t].s:=p;
180           inc(t);
181         end;
182       end
183       else begin
184         t:=0;
185         w:=0;
186         f:=0;
187         if sa[i]>loc then
188         begin
189           q[t].h:=h[i+1];
190           q[t].s:=1;
191           w:=h[i+1]-k+1;
192           inc(t);
193         end;
194       end;
195     end;
196     writeln(ans);
197     readln(k);
198   end;
199 end.
View Code

 

posted on 2015-01-31 23:55  acphile  阅读(148)  评论(0编辑  收藏  举报