• 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
    ",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 }
  • 相关阅读:
    软件工程第一次作业
    软件工程第五次作业——结对编程 小学四则运算自动生成程序
    软件工程第四次作业——结对编程第一次作业
    软件工程第三次作业——最大连续子数组和
    软件工程——第二次作业
    第一篇博客——我的大学
    结对编程第二次作业
    结对编程第一次作业
    软件工程第三次作业
    软件工程第二次作业
  • 原文地址:https://www.cnblogs.com/xln1111/p/8710226.html
Copyright © 2020-2023  润新知