bzoj 4566: [Haoi2016]找相同字符

Description

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。

 

Input

两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母

 

Output

输出一个整数表示答案

 

Sample Input

aabb
bbaa

Sample Output

10
 
后缀自动机: 用类似于求两个串的lcs一样的方法,先对一个串建立sam,然后另外一个串在sam上进行匹配。  好像用广义的后缀自动机也可以做。  
 1 #include<bits/stdc++.h>
 2 using namespace std;  
 3 int const N=200000+10;  
 4 int f[N<<1],ch[N<<1][26],tot,ls,sz[N<<1],num[N],sa[N<<1];  
 5 long long cnt[N<<1],len[N<<1];  
 6 char s1[N],s2[N];  
 7 void add(int c){
 8     int p=ls;  
 9     int np=ls=++tot;  
10     len[np]=len[p]+1; 
11     sz[np]=1;  
12     for(;p&&!ch[p][c];p=f[p]) ch[p][c]=np; 
13     if(!p) f[np]=1;  
14     else {
15         int q=ch[p][c];  
16         if(len[q]==len[p]+1) f[np]=q;
17         else {
18             int nq=++tot;  
19             len[nq]=len[p]+1;  
20             memcpy(ch[nq],ch[q],sizeof(ch[q])); 
21             f[nq]=f[q];  
22             f[q]=f[np]=nq;  
23             for(;p&&ch[p][c]==q;p=f[p]) 
24                 ch[p][c]=nq;  
25         }
26     }
27 }
28 int main(){
29     scanf("%s%s",s1,s2); 
30     int n=strlen(s1); 
31     tot=ls=1; 
32     for(int i=0;i<n;i++) 
33         add(s1[i]-'a');  
34     for(int i=1;i<=tot;i++) num[len[i]]++; 
35     for(int i=1;i<=n;i++) num[i]+=num[i-1]; 
36     for(int i=1;i<=tot;i++) sa[num[len[i]]--]=i;  
37     for(int i=tot;i>=2;i--){
38         int x=sa[i];  
39         int fa=f[x];  
40         sz[fa]+=sz[x]; 
41     }  
42     for(int i=2;i<=tot;i++){
43         int x=sa[i];  
44         int fa=f[x];  
45         cnt[x]=sz[x]*(len[x]-len[fa])+cnt[fa]; 
46     }  
47     int p=1,tmp=0;
48     long long ans=0;  
49     for(int i=0;i<n;i++){
50         int c=s2[i]-97;
51         if(ch[p][c]) { 
52             tmp++; p=ch[p][c];  
53             ans+=(tmp-len[f[p]])*sz[p]+cnt[f[p]];  
54         }else {
55             while (p && !ch[p][c])  p=f[p];  
56             if(!p) {
57                 p=1;tmp=0;
58             }else {
59                 tmp=len[p]+1;  
60                 p=ch[p][c];  
61                 ans+=(tmp-len[f[p]])*sz[p]+cnt[f[p]];  
62             }  
63         } 
64     }
65     cout<<ans<<endl; 
66     return 0; 
67 } 
View Code

 

posted @ 2019-06-27 22:22  zjxxcn  阅读(154)  评论(0编辑  收藏  举报