• 回文自动机+DFS


    题目来源

    [The 2014 ACM-ICPC Asia Xi’an Regional Contest Problem G]

    题目描述

    给你两个字符串,求这两个字符串相同回文串的匹配对数。

    思路分析

    每个字符串建一棵回文树,分别从0结点和1结点两棵树一起往下dfs,对于同一条路径上的结点,一定是相同的回文,然后两个的数量相乘加到answer中。

    时间复杂度

    O(N)

    代码

    /*
    * this code is made by crazyacking
    * Verdict: Accepted
    * Submission Date: 2015-08-22-13.43
    * Time: 0MS
    * Memory: 137KB
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define  LL long long
    #define  ULL unsigned long long
    using namespace std;
    
    const int MAXN = 200050 ;
    const int N = 26;
    LL ans;
    char s[MAXN];
    struct Palindromic_Tree
    {
         int next[MAXN][N];
         int fail[MAXN];
         int cnt[MAXN];
         int num[MAXN];
         int len[MAXN];
         int S[MAXN];
         int last;
         int n ;
         int p ;
         int newnode(int l)
         {
               for(int i = 0 ; i < N ; ++ i) next[p][i] = 0 ;
               cnt[p] = 0 ;
               num[p] = 0 ;
               len[p] = l ;
               return p ++ ;
         }
         void init()
         {
               p = 0 ;
               newnode(0) ;
               newnode(-1) ;
               last = 0 ;
               n = 0 ;
               S[n] = -1 ;
               fail[0] = 1 ;
         }
         int get_fail(int x)
         {
               while(S[n - len[x] - 1] != S[n]) x = fail[x] ;
               return x ;
         }
         void add(int c)
         {
               c -= 'a';
               S[++ n] = c ;
               int cur = get_fail(last);
               if(!next[cur][c])
               {
                     int now = newnode(len[cur] + 2);
                     fail[now] = next[get_fail(fail[cur])][c] ;
                     next[cur][c] = now;
                     num[now] = num[fail[now]] + 1 ;
               }
               last = next[cur][c];
               cnt[last] ++;
         }
         void count() { for(int i = p - 1 ; i >= 0 ; -- i) cnt[fail[i]] += cnt[i]; }
    } t1,t2;
    
    void dfs(int u,int v)
    {
         for(int i=0; i<N; ++i)
         {
               int x=t1.next[u][i];
               int y=t2.next[v][i];
               if(x&&y)
               {
                     ans+=(LL)t1.cnt[x]*t2.cnt[y];
                     dfs(x,y);
               }
         }
    }
    
    int main()
    {
         int t;
         scanf("%d",&t);
         for(int Cas=1; Cas<=t; ++Cas)
         {
               t1.init(),t2.init();
               scanf("%s",s);
               for(int i=0; s[i]; ++i) t1.add(s[i]);
               scanf("%s",s);
               for(int i=0; s[i]; ++i) t2.add(s[i]);
               t1.count(),t2.count();
               ans=0;
               dfs(0,0),dfs(1,1);
               printf("Case #%d: %lld
    ",Cas,ans);
         }
         return 0;
    }
  • 相关阅读:
    【python学习笔记02】python的数据类型2
    元器件选型(一)ESD、TVS参考资料
    【python学习笔记01】python的数据类型
    你不知道的vue生命周期钩子选项(三)
    vue源码解析之选项合并(二)
    vue源码解析之选项合并(一)
    聊聊var与let 在window下面的区别(除开作用域)
    浅谈JavaScript中的防抖和节流
    Redhat6.4下安装Oracle10g
    Ubuntu Server 14.04 集成
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4750472.html
Copyright © 2020-2023  润新知