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

HAOI2016找相同字符

时间:2018-04-03 19:18:32      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:答案   col   pre   mes   顺序   ++i   ace   memcpy   cstring   

bzoj4566 / loj2064

题目

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两个子串中有一个位置不同。 L<=200000
 
做法一:后缀自动机
注意:
  1. 当前匹配到的长度不一定是当前节点的最长长度 所以:在53、57行统计有关当前节点答案的地方,应用 l[f[p]]+1 或是  len-l[f[l]]
  2. 注意拓扑排序的遍历顺序皆为从小到大
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 using namespace std;
 5 const int N=600001;
 6 int lst=1,cnt=1,sz[N],l[N],f[N],c[N][27];
 7 inline void ins(int x){
 8     int p=lst,np=++cnt;lst=np;
 9     l[np]=l[p]+1;sz[np]=1;
10     for(;p&&!c[p][x];p=f[p])c[p][x]=np;
11     if(!p)f[np]=1;
12     else{
13         int q=c[p][x];
14         if(l[q]==l[p]+1)f[np]=q;
15         else{
16             int nq=++cnt;
17             f[nq]=f[q];
18             memcpy(c[nq],c[q],sizeof(c[q]));
19             l[nq]=l[p]+1;
20             f[q]=f[np]=nq;
21             for(;p&&c[p][x]==q;p=f[p])c[p][x]=nq;
22         }
23     }
24 }
25 int n1,n2;
26 char s1[N>>1],s2[N>>1];
27 int tmptmp[N],tp[N],sm[N];
28 inline void TP(){
29     for(int i=1;i<=cnt;++i)++tmptmp[l[i]];
30     for(int i=1;i<=n1;++i)tmptmp[i]+=tmptmp[i-1];
31     for(int i=1;i<=cnt;++i)tp[tmptmp[l[i]]--]=i;
32 }
33 long long ans=0;
34 int main(){
35     scanf("%s%s",s1,s2);n1=strlen(s1);n2=strlen(s2);
36     for(int i=0;i<n1;++i){
37         ins(s1[i]-a);
38     }
39     TP();   
40     for(int i=cnt;i>=1;--i)sz[f[tp[i]]]+=sz[tp[i]];
41     for(int i=2;i<=cnt;++i){
42         sm[tp[i]]=sm[f[tp[i]]]+ sz[tp[i]]*(l[tp[i]]-l[f[tp[i]]]);
43     }// for(int i=1;i<=cnt;++i)printf("sm[%d]=%d sz%d f%d tp%d a%d b%d\n",i,l[i],sz[i],f[i],tp[i],c[i][0],c[i][1]);
44     int p=1,len=0,x;
45     for(int i=0;i<n2;++i){//puts("*");
46         x=s2[i]-a;
47         if(c[p][x]){
48             ++len;p=c[p][x];
49         }else{
50             for(;p&&!c[p][x];p=f[p]);
51             if(!p)len=0,p=1;
52             else{
53                 len=l[p]+1;
54                 p=c[p][x];              
55             }
56         }
57         ans+=(long long)(sm[f[p]]+sz[p]*(len-l[f[p]]));
58     }
59     cout<<ans;
60     return 0;
61 }

 

HAOI2016找相同字符

标签:答案   col   pre   mes   顺序   ++i   ace   memcpy   cstring   

原文地址:https://www.cnblogs.com/xln1111/p/8710226.html

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