Time Limit: 5000MS | Memory Limit: 65536K | |
Total Submissions: 7291 | Accepted: 2417 |
Description
A substring of a string T is defined as:
Given two strings A, B and one integer K, we define S, a set of triples (i, j, k):
You are to give the value of |S| for specific A, B and K.
Input
The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.
1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.
Output
For each case, output an integer |S|.
Sample Input
2 aababaa abaabaa 1 xx xx 0
Sample Output
22 5
这道题需要对height数组分组后,用单调栈优化。对于LCP=L>K的前缀,对答案的贡献是L-K+1.即长度为K,K+1.....L的公共字串。对于每一组,栈里维护height值递增,这样保证了每个height的贡献量为height[i]-K+1,因为有定理LCP(i,j)=min(height[i+1],...height[j])如果在height[i]之后插入一个height[k]
补充:因为rank=i的后缀能与其rank前后的后缀都可能产生公共子串,但此算法只维护其前面的,因此排在A串后缀后面的B串后缀,应该用扫描B串后缀来维护,因为B在A后,以B为参考系,A就在前,这就是为什么要分别扫A和B串的原因。
补充完这段,接着开始:比如我们正在扫A串,那么当B串入栈时,sum均会加上L-K+1,而之后当有height值小的要入栈,此时可以是A串的后缀,他虽然不增加sum的值,但它也起到了阻断作用,它是之前栈里height值>=它的值变废了,因为后面的后缀与栈里算LCP值时,起码要<=这个值,由于栈里原先的元素都加了L-K+1,假设现在入栈的height值为T(T
总之,这道题个人感觉方法很棒!我也是理解了好久,可能上面解释的不太到位吧,还需要各位更深入的研究。
代码:
#include
#include
#define ll long long
#define Maxn 200010
using namespace std;
int r[Maxn],sa[Maxn],rk[Maxn],height[Maxn];
int wa[Maxn],wb[Maxn],rs[Maxn],wv[Maxn];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int n,int m){
int i,j,p,*x=wa,*y=wb;
for(i=0;i=0;i--) sa[--rs[x[i]]]=i;
for(j=1,p=1;p=j) y[p++]=sa[i]-j;
for(i=0;i=0;i--) sa[--rs[wv[i]]]=y[i];
swap(x,y);
for(p=1,x[sa[0]]=0,i=1;iheight[i]){
sum-=len[top]*(st[top]-height[i]);
width+=len[top--];
}
if(sa[i-1]<=la) width+=1,sum+=height[i]-k+1;
st[++top]=height[i];
len[top]=width;
if(sa[i]>la) ans+=sum;
}
}
for(int i=1;iheight[i]){
sum-=(ll)len[top]*(st[top]-height[i]);
width+=len[top--];
}
if(sa[i-1]>la) width+=1,sum+=height[i]-k+1;
st[++top]=height[i];
len[top]=width;
if(sa[i]<=la) ans+=sum;
}
}
printf("%lld\n",ans);
}
return 0;
}