• 【BZOJ4566】【HAOI2016】找相同字符


    后缀自动姬好,好写好调好ac

    原题:

    给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
    个子串中有一个位置不同。
    1 <=n1, n2<= 20000
     
    之前写了个后缀数组+并查集的,因为我只会后缀数组……
    后看看dalao们纷纷使用后缀自动姬秒题,决定提高一下自己姿势水平,学一发后缀自动姬
    然后根本无法理解啊quq,现在板子差不多理解了,但是自动姬上做DP的延伸还是不能理解quq
    多做题应该就能理解了吧……
    这题dp具体思路是啥我也没搞懂,直接上结论
    每个点的贡献:|right(x)|*(max[x]-max[fa[x]])
    具体贡献到答案上,就搞一个b在当前节点上匹配的公共长度l,然后对答案的贡献就是|right(x)|*(l-max[fa[x]])
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 #define ll long long
     8 int rd(){int z=0,mk=1;  char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
    10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    11     return z*mk;
    12 }
    13 char a[210000],b[210000];  int n,m;
    14 int nxt[810000][26],fa[810000],mx[810000],sz[810000];
    15 int lst=1,tt=1;
    16 int cnt[810000],cntrk[810000];
    17 ll f[810000];
    18 void ist(int x){
    19     int p=lst,np=lst=++tt;
    20     mx[np]=mx[p]+1;  sz[np]=1;
    21     while(!nxt[p][x] && p)  nxt[p][x]=np,p=fa[p];
    22     if(!p)  fa[np]=1;
    23     else{
    24         int q=nxt[p][x];
    25         if(mx[p]+1==mx[q])  fa[np]=q;
    26         else{
    27             int nq=++tt;  mx[nq]=mx[p]+1;
    28             memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
    29             fa[nq]=fa[q],fa[q]=fa[np]=nq;
    30             while(nxt[p][x]==q)  nxt[p][x]=nq,p=fa[p];
    31         }
    32     }
    33 }
    34 void gtcntrk(){
    35     for(int i=1;i<=tt;++i)  ++cnt[mx[i]];
    36     for(int i=1;i<=n;++i)  cnt[i]+=cnt[i-1];
    37     for(int i=tt;i;--i)  cntrk[cnt[mx[i]]--]=i;
    38 }
    39 void gtf(){
    40     for(int i=tt;i;--i)  sz[fa[cntrk[i]]]+=sz[cntrk[i]];
    41     for(int i=1;i<=tt;++i)
    42         f[cntrk[i]]=f[fa[cntrk[i]]]+(ll)sz[cntrk[i]]*(mx[cntrk[i]]-mx[fa[cntrk[i]]]);
    43 }
    44 int main(){//freopen("ddd.in","r",stdin);
    45     scanf("%s%s",a+1,b+1);  n=strlen(a+1),m=strlen(b+1);
    46     for(int i=1;i<=n;++i)  ist(a[i]-'a');
    47     gtcntrk(),gtf();
    48     ll bwl=0;  int l=0,tmp=1,x;
    49     for(int i=1;i<=m;++i){
    50         x=b[i]-'a';
    51         if(nxt[tmp][x])  tmp=nxt[tmp][x],++l;
    52         else{
    53             while(!nxt[tmp][x] && tmp)  tmp=fa[tmp];
    54             if(!tmp)  tmp=1,l=0;
    55             else  l=mx[tmp]+1,tmp=nxt[tmp][x];
    56         }
    57         if(tmp!=1)  bwl+=f[fa[tmp]]+(ll)sz[tmp]*(l-mx[fa[tmp]]);
    58     }
    59     cout<<bwl<<endl;
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    LuoguP2765 魔术球问题
    LuoguP1402 酒店之王
    luoguP4313 文理分科
    玲珑杯 1138
    codeforces 822 D. My pretty girl Noora(dp+素数筛)
    codeforces 822 C. Hacker, pack your bags!(思维+dp)
    51nod 1376 最长递增子序列的数量(不是dp哦,线段树 +  思维)
    hdu4565 So Easy!(矩阵快速幂)
    atcode E
    atcoder D
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6544869.html
Copyright © 2020-2023  润新知