[BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp

4566: [Haoi2016]找相同字符

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 1212  Solved: 694
[Submit][Status][Discuss]

Description

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

 

Input

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

 

Output

输出一个整数表示答案

 

Sample Input

aabb
bbaa

Sample Output

10

HINT

 

Source

 

时隔许久后重新获得了后缀自动机技能。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstdio>
 7 #define maxn 200005
 8 #define ll long long
 9 using namespace std;
10 inline int read() {
11     int x=0,f=1;char ch=getchar();
12     for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
13     for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
14     return x*f;
15 }
16 struct SUF {
17     int sz[maxn*2],link[maxn*2],step[maxn*2],son[maxn*2][26],v[maxn*2],pos[maxn*2];
18     int nxt[maxn*2],head[maxn*2],tto[maxn*2],tot;
19     int cnt,last;
20     SUF() {last=cnt=1;memset(head,-1,sizeof(head));}
21     void extend(int c) {
22         int p=last,np=last=++cnt;step[np]=step[p]+1;sz[np]=1;
23         while(p&&!son[p][c]) son[p][c]=np,p=link[p];
24         if(!p) link[np]=1;
25         else {
26             int q=son[p][c];
27             if(step[q]==step[p]+1) link[np]=q;
28             else {
29                 int nq=++cnt;
30                 memcpy(son[nq],son[q],sizeof(son[q]));
31                 link[nq]=link[q];link[q]=link[np]=nq;
32                 step[nq]=step[p]+1;
33                 while(son[p][c]==q&&p) son[p][c]=nq,p=link[p];
34             }
35         }
36     }
37     void pre() {
38         for(int i=1;i<=cnt;i++) v[step[i]]++;
39         for(int i=1;i<=cnt;i++) v[i]+=v[i-1];
40         for(int i=cnt;i>=1;i--) pos[v[step[i]]--]=i;
41         for(int i=cnt;i>=1;i--) sz[link[pos[i]]]+=sz[pos[i]];
42     }
43     ll f[maxn*2];
44     void dfs(int x) {
45         f[x]+=1ll*sz[x]*(step[x]-step[link[x]]);
46         for(int i=head[x];i>=0;i=nxt[i]) {
47             int to=tto[i];f[to]+=f[x];dfs(to);
48         }
49     }
50     void add(int u,int v) {
51         nxt[tot]=head[u];tto[tot]=v;head[u]=tot++;
52     }
53 }t;
54 char ch[maxn];
55 int main() {
56     scanf("%s",ch+1);int len=strlen(ch+1);
57     for(int i=1;i<=len;i++) t.extend(ch[i]-'a');
58     t.pre();
59     scanf("%s",ch+1);len=strlen(ch+1);
60     for(int i=1;i<=t.cnt;i++) if(t.link[i]) t.add(t.link[i],i);t.dfs(1);
61     int now=1,l=0;ll ans=0;
62     for(int i=1;i<=len;i++) {
63         int to=ch[i]-'a';
64         while(now&&!t.son[now][to]) now=t.link[now];
65         if(!now) now=1,l=0;
66         else l=min(l,t.step[now])+1,now=t.son[now][to];
67         ans+=t.f[t.link[now]];ans+=1ll*(l-t.step[t.link[now]])*t.sz[now];
68     }
69     printf("%lld\n",ans);
70 }
View Code

 

posted @ 2018-11-27 18:45  wls001  阅读(185)  评论(0编辑  收藏  举报