A string is palindrome, if the string reads the same backward and forward. For example, strings like "a", "aa", "appa", "queryreuq" are all palindromes.

For given empty string S, you should process following two queries :

  1. Add a lower case alphabet at the back of S.
  2. Remove a character at the back of S.

After processing a query, you should count the number of palindrome substring in S. For string S and integers i,  j (1 ≤ i ≤ j ≤ |S|), represents a substring from ith to jth character of S. You should print out the number of integer pairs (i,  j) where is palindrome.

Input

Input consists of two lines.

In the first line, Q, the number of queries is given. (1 ≤ Q ≤ 10, 000)

In the second line, the query is given as string of length Q. ith character Ki denotes the ith query.

Ki is '-' or lower case alphabet ('a', 'b', ..., 'z') (without quotes).

If the character is '-', you should remove a character at the back of S. If the character is lower case alphabet, you should add a character Ki at the back of S.

It is guaranteed that length of S is always positive after the query.

Output

Print out Q space-separated integers in the first line. i-th integer should be the answer of the ith query.

Example

Input
17
qu-uer-ryr-reu-uq
Output
1 2 1 2 3 4 3 4 5 7 5 7 9 11 9 11 13 

题意:现在有一个空的字符串S,S每次在末尾添加一个字符,或者删去末尾的字符(输入'-'号表示)。现在让你求每次操作后字符串S的回文串个数。

思路:mad,队友写了一发回文树,但是他是每次操作都暴力建树,暴力求的,所以为了在线求而不是每次重新建树,我还现学了一下回文树,挺简单的。

就是每次fail指针跑就完事了。 比后缀自动机好理解多了。 那么这个题,每次我们加入一个字符,那就加到回文树里,如果删去,则在fail链上的所有点都-1,如果-1后变为0,则删去那个点(sz标记为-1)。

但是在全部都是aaaaaaa...这种情况下,复杂度还是有点高,和暴力的复杂度差不多,复杂度小于(N^2)/4,不过N为10000可以过。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
char c[maxn],s[maxn]; int fcy[maxn],pos[maxn];
struct Palindromic_Tree
{
struct Node
{
int son[];
int fail,len;
}t[maxn];
int last,tot,sz[maxn];
void init()
{
memset(sz,-,sizeof(sz));
t[++tot].len=-; //-1是因为后面找fail是时候可以break
t[].fail=t[].fail=; //奇偶两棵树
}
int del(int Now)
{
int res=;
while(Now>){
if(sz[Now]==-) continue;
if(sz[Now]==) sz[Now]=-;
else sz[Now]--;
res++; Now=t[Now].fail;
} return res;
}
void add(int c,int n)
{
int p=pos[n-];
while(s[n-t[p].len-]!=s[n]) p=t[p].fail;
if(!t[p].son[c])
{
int v=++tot,k=t[p].fail;
t[v].len=t[p].len+;
while(s[n-t[k].len-]!=s[n]) k=t[k].fail;
t[v].fail=t[k].son[c];
t[p].son[c]=v;
sz[v]=;
}
last=t[p].son[c];
int Now=last,res=;
while(Now>){
if(sz[Now]!=-) sz[Now]++,res++;
else sz[Now]=,res++;
Now=t[Now].fail;
}
fcy[n]=res; pos[n]=last;
}
}T;
int main()
{
T.init(); int N,L=,ans=;
scanf("%d%s",&N,c+);
pos[]=;
rep(i,,N){
if(c[i]=='-'){
ans-=T.del(pos[L]); L--;
}
else {
L++; s[L]=c[i];
T.add(c[i]-'a',L);
ans+=fcy[L];
}
printf("%d ",ans);
}
return ;
}

Gym - 101806Q:QueryreuQ(回文树)的更多相关文章

  1. 回文树&后缀自动机&后缀数组

    KMP,扩展KMP和Manacher就不写了,感觉没多大意思.   之前感觉后缀自动机简直可以解决一切,所以不怎么写后缀数组.   马拉车主要是通过对称中心解决问题,有的时候要通过回文串的边界解决问题 ...

  2. 回文树 Palindromic Tree

    回文树 Palindromic Tree 嗯..回文树是个什么东西呢. 回文树(或者说是回文自动机)每个节点代表一个本质不同的回文串. 首先它类似字典树,每个节点有SIGMA个儿子,表示对应的字母. ...

  3. HDU3948 & 回文树模板

    Description: 求本质不同回文子串的个数 Solution: 回文树模板,学一学贴一贴啊... Code: /*================================= # Cre ...

  4. 2014-2015 ACM-ICPC, Asia Xian Regional Contest G The Problem to Slow Down You 回文树

    The Problem to Slow Down You Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjud ...

  5. 【CF245H】Queries for Number of Palindromes(回文树)

    [CF245H]Queries for Number of Palindromes(回文树) 题面 洛谷 题解 回文树,很类似原来一道后缀自动机的题目 后缀自动机那道题 看到\(n\)的范围很小,但是 ...

  6. 【CF17E】Palisection(回文树)

    [CF17E]Palisection(回文树) 题面 洛谷 题解 题意: 求有重叠部分的回文子串对的数量 所谓正难则反 求出所有不重叠的即可 求出以一个位置结束的回文串的数量 和以一个位置为开始的回文 ...

  7. 【SPOJ】NUMOFPAL - Number of Palindromes(Manacher,回文树)

    [SPOJ]NUMOFPAL - Number of Palindromes(Manacher,回文树) 题面 洛谷 求一个串中包含几个回文串 题解 Manacher傻逼题 只是用回文树写写而已.. ...

  8. 【BZOJ2160】拉拉队排练(回文树)

    [BZOJ2160]拉拉队排练(回文树) 题面 BZOJ 题解 看着题目, 直接构建回文树 求出每个回文串的出现次数 直接按照长度\(sort\)一下就行了 然后快速幂算一下答案就出来了 这题貌似可以 ...

  9. 【CF932G】Palindrome Partition(回文树,动态规划)

    [CF932G]Palindrome Partition(回文树,动态规划) 题面 CF 翻译: 给定一个串,把串分为偶数段 假设分为了\(s1,s2,s3....sk\) 求,满足\(s_1=s_k ...

随机推荐

  1. 把旧系统迁移到.Net Core 2.0 日记 (18) --JWT 认证(Json Web Token)

    我们最常用的认证系统是Cookie认证,通常用一般需要人工登录的系统,用户访问授权范围的url时,会自动Redirect到Account/Login,登录后把认证结果存在cookie里. 系统只要找到 ...

  2. oracle中计算两个日期的相差天数、月数、年数、小时数、分钟数、秒数等

    oracle如何计算两个日期的相差天数.月数.年数.小时数.分钟数.秒数 1.相差天数(两个日期相减) --Oracle中两个日期相差天数-- select TO_NUMBER(TO_DATE('20 ...

  3. JAVA8的LocalDateTime使用心得和工具类

    今天做不成的事,明天也不会做好. 同学们,JAVA8出了这么久,不知道你们有没有用过它的LocalDateTime类型,还是依然用Date类型呢?其实,LocalDateTime类型给我们提供了很多便 ...

  4. js代码之编程习惯

    编程习惯: 异常处理 如果你没有使用异常处理的习惯,这可能是因为你并未真正的理解它的作用.当你正确使用异常处理之后,你会发现你的代码最显著的变化就是:少了很多的 if-else 语句 . 虽然在 JS ...

  5. R语言中的采样与生成组合

    不放回采样:sample(1:10, 5, replace = FALSE) 生成组合:

  6. day06字典类型

    基本使用: 1.用途:用来存多个(不同种类的)值 2定义方式:在{}内用逗号分隔开多个key:value的元素,其中value可以是任意数据类型,而key的功能通常是用来描述value的,所以key通 ...

  7. xml的方式配置AOP:Aspect Oriented Programming

    在某些类中, 什么时机, 做什么事情 切入点(point-cut): 在某些类中(Class<?>[] itfc = new Class<?>[] { IStudentServ ...

  8. xml解析与生成的学习资料

    xml解析与生成的学习资料:http://blog.csdn.net/u012325167/article/category/6129813 ----------------------------- ...

  9. 3.2 C++继承方式

    参考: http://www.weixueyuan.net/view/6359.html  总结: 子类继承父类,继承方式将限制父类的成员属性在子类中的访问权限,子类访问父类的成员,也需要遵循其成员的 ...

  10. Docker小白从零入门到实战系列【二】

    1.安装好Centos 7 2.关闭SELINUX sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/configsetenfo ...