• Luogu P5685 [JSOI2013]快乐的 JYY


    我们对两个 PAM 同时开始 dfs ,因为起始状态相同,那么如果遇到相同的转移就说明有相同的状态,把 (sz_x imes sz_y) 作为贡献加到答案里面即可。注意要分别从两个根 dfs

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define R register int
    #define ll long long
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=50010;
    int n;
    ll ans;
    char s[N];
    struct PAM {
      int tot,lst,fa[N],c[N][26],len[N],sz[N];
      inline void init() {len[fa[fa[1]=0]=tot=1]=-1;}
      inline int jmp(int p,int i) 
        {while(s[i-len[p]-1]!=s[i]) p=fa[p]; return p;}
      inline void add(int ch,int i) {
        R p=jmp(lst,i); if(!c[p][ch]) {
          R np=++tot; len[np]=len[p]+2;
          R t=jmp(fa[p],i);
          fa[np]=c[t][ch],c[p][ch]=np;
        } ++sz[lst=c[p][ch]];
      }
    }p1,p2;
    inline void dfs(int p,int q) {
      ans+=1ll*p1.sz[p]*p2.sz[q];
      for(R i=0;i<26;++i) 
        if(p1.c[p][i]&&p2.c[q][i]) dfs(p1.c[p][i],p2.c[q][i]);
    }
    inline void main() {
      scanf("%s",s+1),n=strlen(s+1),p1.init();
      for(R i=1;i<=n;++i) p1.add(s[i]-'A',i);
      for(R i=p1.tot;i>=2;--i) p1.sz[p1.fa[i]]+=p1.sz[i];
      scanf("%s",s+1),n=strlen(s+1),p2.init(); 
      for(R i=1;i<=n;++i) p2.add(s[i]-'A',i);
      for(R i=p2.tot;i>=2;--i) p2.sz[p2.fa[i]]+=p2.sz[i];
      p1.sz[0]=p1.sz[1]=p2.sz[0]=p2.sz[1]=0;
      dfs(1,1),dfs(0,0); 
      printf("%lld
    ",ans);
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.16

  • 相关阅读:
    CSS learnning...
    软件工程课程建议
    结对编程(三)
    结对编程(二)
    关于结对编程的感想
    关于“Durian”调查问卷的心得体会
    我的软件工程课目标
    软件工程课程建议
    进阶版《结对编程》
    结对编程实现四则运算
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12202882.html
Copyright © 2020-2023  润新知