HAOI2016找相同字符

Posted xln1111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAOI2016找相同字符相关的知识,希望对你有一定的参考价值。

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找相同字符的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4566:[Haoi2016]找相同字符

bzoj 4566 [Haoi2016]找相同字符SA

[HAOI2016]找相同字符(后缀数组+单调栈)

P3181 [HAOI2016]找相同字符

[HAOI2016]找相同字符(广义SAM)

[HAOI 2016] 找相同字符