HDU.5394.Trie in Tina Town(回文树)

题目链接


\(Description\)

给定一棵\(Trie\)。求\(Trie\)上所有回文串 长度乘以出现次数 的和。这里的回文串只能是从上到下的一条链。
节点数\(n\leq 2\times 10^6\),字符集为a,b,c,d

\(Solution\)

如果不是树,就是回文树模板。对于树,DFS \(x\)的每个儿子的时候都用在\(x\)处的\(las\)即可,也就是按深度存一个\(las\)数组,每次用\(las[dep-1]\)做\(las\)去插入即可。(也可以回溯的时候直接删节点)
每次插入产生的贡献怎么算。。?
令\(ans[x]\)表示\(x\)节点(状态)处的贡献,插入后到了\(x\)节点答案就加上\(ans[x]\)。
对于新建的\(x\)节点,\(ans[x]=len[x]+ans[fail[x]]\)(除了新产生的串,剩下的贡献就是\(fail[x]\)的状态的贡献了)。

加了fread之后惊呆了= =拿到了hdu上第一个rank1= =
果然不是我算法效率问题。。。

话说我为什么不需要开栈啊


//1092MS    151236K(fread) <- 7784MS    149280K
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 2000000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e6+6;

char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-48,c=gc());
    return now;
}

struct PAM
{
    int s[N],H[N],nxt[N],tot,las[N],son[N][4],len[N],fail[N];
    LL Ans,ans[N];
    char tmp[N];
    inline void Init()
    {
        las[0]=tot=1, fail[0]=1, len[1]=-1, s[0]=-1;
        memset(son[0],0,sizeof son[0]), memset(son[1],0,sizeof son[1]);
    }
    inline int Find(int x,int n)
    {
        while(s[n]!=s[n-len[x]-1]) x=fail[x];
        return x;
    }
    void Insert(int c,int n)
    {
        s[n]=c;
        int p=Find(las[n-1],n);
        if(!son[p][c])
        {
            int np=++tot;
            memset(son[np],0,sizeof son[np]);
            fail[np]=son[Find(fail[p],n)][c];
            son[p][c]=np, len[np]=len[p]+2;
            ans[np]=ans[fail[np]]+len[np];
        }
        Ans+=ans[las[n]=son[p][c]];
    }
    void DFS(int x,int dep)
    {
        for(int v=H[x]; v; v=nxt[v])
            Insert(tmp[v]-'a',dep), DFS(v,dep+1);
    }
    void Solve()
    {
        Init();
        const int n=read();
        for(int i=1; i<=n; ++i)
        {
            while(!isalpha(tmp[i]=gc()));
            int fa=read();
            nxt[i]=H[fa], H[fa]=i;
        }
        Ans=0, DFS(0,1), printf("%lld\n",Ans);
        memset(H,0,n+1<<2);
    }
}pam;

int main()
{
    for(int T=read(); T--; pam.Solve());
    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/10346250.html

时间: 2024-07-30 03:06:41

HDU.5394.Trie in Tina Town(回文树)的相关文章

HDU 5157 Harry and magic string(回文树)

Harry and magic string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 223    Accepted Submission(s): 110 Problem Description Harry got a string T, he wanted to know the number of T's disjoint

HDU 5658 CA Loves Palindromic(回文树)

CA Loves Palindromic Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 301    Accepted Submission(s): 131 Problem Description CA loves strings, especially loves the palindrome strings. One day

HDU 6599 I Love Palindrome String (回文树+hash)

题意 找如下子串的个数: (l,r)是回文串,并且(l,(l+r)/2)也是回文串 思路 本来写了个回文树+dfs+hash,由于用了map所以T了 后来发现既然该子串和该子串的前半部分都是回文串,所以该子串的前半部分和后半部分是本质相同的! 于是这个log就去掉了 代码 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring>

HDU 5371(Hotaru&#39;s problem-2次回文串)

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2432    Accepted Submission(s): 841 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playin

hdu 6599 I Love Palindrome String 回文自动机

hdu 6599 I Love Palindrome String 回文自动机 当个回文自动机的模板 题意 给一个串S,求长度为i的"特殊回文串"个数,"特殊回文串"要求是回文串,并且自己的一半也是回文串. 思路 求回文串个数相关,优先考虑使用回文自动机,"特殊回文串"要求是回文串,并且自己的一半也是回文串,显然就是fail树扒出来dfs搞一下,记录dfs路径上有没有长度一半的回文串即可. PS:因为fail指针的意义是最长后缀回文,反过来路径显

HDU - 5157 :Harry and magic string (回文树)

Sample Input aca aaaa Sample Output 3 15 题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串. 思路:可以用回文树求出以每个位置结尾的回文串数,那么累加得到前缀和: 倒着再做一遍得到每个位置为开头的回文串数,乘正向求出的前缀和即可. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define

HDU - 5421:Victor and String (回文树,支持首尾插入新字符)

Sample Input 6 1 a 1 b 2 a 2 c 3 4 8 1 a 2 a 2 a 1 a 3 1 b 3 4 Sample Output 4 5 4 5 11 题意:多组输入,开始字符串为空,支持4中操作: 1,在字符串首加字符: 2,在字符串尾加字符: 3,查询字符串不同本质的回文串个数: 4,查询回文串个数总和 思路:因为支持首尾加入,所以和常规的回文树有些不同. 参考了YYB的博客. 发现首尾互相影响,当且仅当整个字符串是回文串. 其他情况两头正常加即可. #include

回文树

(没有坑怎么填?) 最近膜了一些关于回文串的题目,感到非常有意思,遂开篇记录. 在逛UOJ的题目时发现了vfk添上了新题,APIO 2014的题目.本身是一件很正常的事,而它事实上也没有变成什么了不得的事.我看到了Palindrome这个标题---回文串已经烂大街了,没什么新意.不过我很早就向学习回文树这东西了,久仰其大名而未尝真正去了结果它,于是我就顺手撸了一把豪哥的论文,发现他讲解的实在是晦涩难懂---论文的通病,就是虽然表述没有歧义,但是难以理解.嘛,然后我就找了几个标程,发现回文树这东西

CF17E Palisection(回文树)

题意翻译 给定一个长度为n的小写字母串.问你有多少对相交的回文子 串(包含也算相交) . 输入格式 第一行是字符串长度n(1<=n<=2*10^6),第二行字符串 输出格式 相交的回文子串个数%51123987 Translated by liyifeng 题目描述 In an English class Nick had nothing to do at all, and remembered about wonderful strings called palindromes. We sh