[BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp
4566: [Haoi2016]找相同字符
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1212 Solved: 694
[Submit][Status][Discuss]
Description
给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。
Input
两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母
Output
输出一个整数表示答案
Sample Input
aabb
bbaa
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 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~