码迷,mamicode.com
首页 > 其他好文 > 详细

4566. [HAOI2016]找相同字符【后缀自动机】

时间:2018-07-23 17:16:35      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:相同   后缀自动机   har   amp   n+1   mes   大于   put   emc   

Description

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

Input

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

Output

输出一个整数表示答案

Sample Input

aabb
bbaa

Sample Output

10
 
很容易可以想到,我们要对字符串A建立SAM,然后用B串在A上跑
只要能匹配到这个节点,那么它顺着fa指针向上的那一串节点都可以产生贡献。
每个节点的贡献是$|R(s)|*max{(min{Max,now}-Min+1),0}$,now为当前匹配长度
实际上当匹配到某个节点s的时候,now一定大于等于fa(s)
所以上面的节点直接用Max更新就可以。需要特判的只是当前的节点
 
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (400000+1000)
 5 using namespace std;
 6 
 7 char s[N],t[N];
 8 long long Ans;
 9 
10 struct SAM
11 {
12     int son[N][28],fa[N],step[N],right[N],wt[N],od[N];
13     int p,q,np,nq,last,cnt;
14     SAM(){last=++cnt;}
15     
16     void Insert(int x)
17     {
18         p=last; np=last=++cnt; step[np]=step[p]+1; right[np]=1;
19         while (!son[p][x] && p) son[p][x]=np,p=fa[p];
20         if (!p) fa[np]=1;
21         else
22         {
23             q=son[p][x];
24             if (step[p]+1==step[q]) fa[np]=q;
25             else
26             {
27                 nq=++cnt; step[nq]=step[p]+1;
28                 memcpy(son[nq],son[q],sizeof(son[q]));
29                 fa[nq]=fa[q]; fa[q]=fa[np]=nq;
30                 while (son[p][x]==q) son[p][x]=nq,p=fa[p];
31             }
32         }
33     }
34     void Init()
35     {
36         int len=strlen(s);
37         for (int i=1; i<=cnt; ++i) wt[step[i]]++;
38         for (int i=1; i<=len; ++i) wt[i]+=wt[i-1];
39         for (int i=cnt; i>=1; --i) od[wt[step[i]]--]=i;
40         for (int i=cnt; i>=1; --i) right[fa[od[i]]]+=right[od[i]];
41     }
42     void Solve(char s[])
43     {
44         int now=1,len=strlen(s),temp=0;
45         for (int i=0; i<len; ++i)
46         { 
47             while (now && !son[now][s[i]-a]) 
48                 now=fa[now],temp=step[now];
49             if (now==0){now=1; continue;}
50             now=son[now][s[i]-a],temp++;
51             Ans+=1ll*right[now]*(temp-step[fa[now]]);
52             int t=now;
53             while (fa[t]) t=fa[t],Ans+=1ll*right[t]*(step[t]-step[fa[t]]);
54         }
55     }
56 }SAM;
57 
58 int main()
59 {
60     scanf("%s%s",s,t);
61     int len=strlen(s);
62     for (int i=0; i<len; ++i)
63         SAM.Insert(s[i]-a);
64     SAM.Init(); 
65     SAM.Solve(t);
66     printf("%lld",Ans);
67 }

4566. [HAOI2016]找相同字符【后缀自动机】

标签:相同   后缀自动机   har   amp   n+1   mes   大于   put   emc   

原文地址:https://www.cnblogs.com/refun/p/9355521.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!