天天看點

HDU 5394 Trie in Tina Town

Problem Description

Tina Town is a friendly place. People there care about each other.

A trie which was planted by the first mayor of Tina Town grows in the center of the town.

We define a palindrome substring in a trie a string that is a suffix of a string which the path from the root to any node represents and the string is a palindrome. Two palindromes are different if and only if their positions are different. Now, Tina wants to know the sum of the length of all palindrome substrings. Tina didn’t know the answer so she asked you to find out the answer for her.

Input

The first line contains a integer – number of cases

For each case, the first line is an integer 

N representing the number of nodes in trie except the root.

The following 

N lines contains a letter between 

a and 

d – the letter that node 

n[i] stores and a number 

f[i] – the index of 

n[i]’s father. It’s guaranteed that 

fa[i]≤i. If 

fa[i]=0 n[i] is the root.

T≤10,N≤2∗106

Output

The first line contains a integer – number of cases

For each case, the first line is an integer 

N representing the number of nodes in trie except the root.

The following 

N lines contains a letter between 

a and 

d – the letter that node 

n[i] stores and a number 

f[i] – the index of 

n[i]’s father. It’s guaranteed that 

fa[i]≤i. If 

fa[i]=0 n[i] is the root.

T≤10,N≤2∗106

Sample Input

2
5
a 0
a 1
a 2
b 1
b 4
5
a 0
a 1
a 2
b 1
a 4      

Sample Output

14
15      

Hint

#pragma comment(linker, "/STACK:102400000,102400000")
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int maxn = 2e6 + 10;
int T, n, ft[maxn], nt[maxn], x;
char s[maxn], ch;
LL ans;

struct PalindromicTree
{
  const static int maxn = 2e6 + 10;
  const static int size = 4;
  int next[maxn][size], sz, tot;
  int fail[maxn], len[maxn], last[maxn], pre[maxn];
  LL cnt[maxn];
  char s[maxn];
  void clear()
  {
    len[1] = -1; len[2] = 0;
    fail[1] = fail[2] = 1;
    cnt[1] = cnt[2] = tot = 0;
    last[0] = (sz = 3) - 1;
    memset(next[1], 0, sizeof(next[1]));
    memset(next[2], 0, sizeof(next[2]));
  }
  int Node(int length)
  {
    memset(next[sz], 0, sizeof(next[sz]));
    len[sz] = length;      return sz;
  }
  int getfail(int x)
  {
    while (s[tot] != s[tot - len[x] - 1]) x = fail[x];
    return x;
  }
  LL add(char pos)
  {
    int x = (s[++tot] = pos) - 'a', y = getfail(last[tot - 1]);
    if (next[y][x]) { last[tot] = next[y][x]; pre[tot] = 0; }
    else {
      last[tot] = next[y][x] = Node(len[y] + 2);
      pre[tot] = y;
      fail[sz] = len[sz] == 1 ? 2 : next[getfail(fail[y])][x];
      cnt[sz] = cnt[fail[sz]] + len[sz];        ++sz;
    }
    return cnt[last[tot]];
  }
  void del(char pos)
  {
    int x = pos - 'a';
    if (pre[tot])
    {
      next[pre[tot]][x] = 0;
      --sz;
    }
    --tot;
  }
}solve;

inline int get()
{
  while ((ch = getchar()) < '0' || ch > '9');
  int x = ch - '0';
  while ((ch = getchar()) >= '0' && ch <= '9') x = x * 10 + ch - '0';
  return x;
}

void dfs(int x)
{
  for (int i = ft[x]; i != -1; i = nt[i])
  {
    ans += solve.add(s[i]);
    dfs(i);
    solve.del(s[i]);
  }
}

int main()
{
  scanf("%d", &T);
  while (T--)
  {
    solve.clear();
    scanf("%d", &n);
    for (int i = 0; i <= n; i++) ft[i] = -1;
    for (int i = 1; i <= n; i++)
    {
      //while ((s[i] = getchar()) < 'a' || ch > 'd');
      //x = get(); nt[i] = ft[x];    ft[x] = i;
      scanf("%s%d", s + i, &x);
      nt[i] = ft[x];    ft[x] = i;
    }
    dfs(ans = 0);
    printf("%lld\n", ans);
  }
  return 0;
}