POJ 3415 Common Substrings

Description

A substring of a string T is defined as:

T(ik)=TiTi+1...Ti+k-1, 1≤ii+k-1≤|T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

S = {(ijk) | kKA(ik)=B(jk)}.

You are to give the value of |S| for specific AB 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

题目大意:
给定两串A,B,找出A,B的长度大于k的公共子串的个数

题解:
显然后缀数组,将两个串合并 然后显然中间加一个‘#’阻断height越界
然后会发现求出high之后两串若分属A,B两串 显然 对答案贡献为lcp-k+1
再根据老套路 利用 height 递增的性质去维护单调栈,记录栈中lcp-k+1的值的总和 tot
如果当前height[i]大于栈顶就统计

如果height[i]<=栈顶 我们直接将栈顶和height[i]合并
调了很久最后发现把l开成了char = =|
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 const int N=400005;
10 int s[N];char S1[N],S2[N];int n,l,tmp[N],rk[N],sa[N],high[N],K,k;
11 bool comp(int i,int j){
12     if(rk[i]!=rk[j])return rk[i]<rk[j];
13     int ri=i+k<=n?rk[i+k]:-1;
14     int rj=j+k<=n?rk[j+k]:-1;
15     return ri<rj;
16 }
17 void Getsa(){
18     for(int i=1;i<=n;i++){
19         sa[i]=i;rk[i]=s[i];
20     }
21     for(k=1;k<=n;k<<=1){
22         sort(sa+1,sa+n+1,comp);
23         for(int i=1;i<=n;i++)tmp[sa[i]]=tmp[sa[i-1]]+comp(sa[i-1],sa[i]);
24         for(int i=1;i<=n;i++)rk[i]=tmp[i];
25     }
26 }
27 void Gethight(){
28     int h=0,j;
29     for(int i=1;i<=n;i++){
30         j=sa[rk[i]-1];
31         if(h)h--;
32         for(;i+h<=n && j+h<=n;h++)if(s[i+h]!=s[j+h])break;
33         high[rk[i]-1]=h;
34     }
35 }
36 ll ans=0;
37 struct stacker{
38     int lcp,cnt;
39 }st[N<<1];
40 void Getanswer()
41 {
42     ll tot=0,cnt=0;int top=0;
43     for(int i=1;i<n;i++){
44        if(high[i]<K){
45             top=tot=0;
46             continue;
47         }
48         cnt=0;
49         if(sa[i]<l)cnt++,tot+=high[i]-K+1;
50         while(top && high[i]<=st[top].lcp){
51             tot-=(ll)(st[top].lcp-high[i])*st[top].cnt;
52             cnt+=st[top].cnt;
53             top--;
54         }
55         st[++top].lcp=high[i];st[top].cnt=cnt;
56         if(sa[i+1]>l)ans+=tot;
57     }
58     tot=0;top=0;cnt=0;
59     for(int i=1;i<n;i++){
60        if(high[i]<K){
61             top=tot=0;
62             continue;
63         }
64         cnt=0;
65         if(sa[i]>l)cnt++,tot+=high[i]-K+1;
66         while(top && high[i]<=st[top].lcp){
67             tot-=(ll)(st[top].lcp-high[i])*st[top].cnt;
68             cnt+=st[top].cnt;
69             top--;
70         }
71         st[++top].lcp=high[i];st[top].cnt=cnt;
72         if(sa[i+1]<l)ans+=tot;
73     }
74 }
75 void work(){
76     n=0;ans=0;
77     scanf("%s%s",S1,S2);
78     l=strlen(S1);
79     for(int i=0;i<l;i++)s[++n]=S1[i];
80     s[++n]='#';l++;
81     for(int i=0,sz=strlen(S2);i<sz;i++)s[++n]=S2[i];
82     s[n+1]=0;
83     Getsa();
84     Gethight();
85     Getanswer();
86     printf("%lld
",ans);
87 }
88 int main()
89 {
90     freopen("pp.in","r",stdin);
91     freopen("pp.out","w",stdout);
92     while(scanf("%d",&K))
93         {
94             if(!K)break;
95             work();
96         }
97     return 0;
98 }
View Code


 
原文地址:https://www.cnblogs.com/Yuzao/p/7163054.html