hdu 5421 回文树

来源:互联网 发布:如何注册淘宝旺旺 编辑:程序博客网 时间:2024/06/05 06:16

Victor and String

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/262144 K (Java/Others)
Total Submission(s): 56    Accepted Submission(s): 25


Problem Description
Victor loves to play with string. He thinks a string is charming as the string is a palindromic string.

Victor wants to play n times. Each time he will do one of following four operations.

Operation 1 : add a char c to the beginning of the string.

Operation 2 : add a char c to the end of the string.

Operation 3 : ask the number of different charming substrings.

Operation 4 : ask the number of charming substrings, the same substrings which starts in different location has to be counted.

At the beginning, Victor has an empty string.
 

Input
The input contains several test cases, at most 5 cases.

In each case, the first line has one integer n means the number of operations.

The first number of next n line is the integer op, meaning the type of operation. If op=1 or 2, there will be a lowercase English letters followed.

1n100000.
 

Output
For each query operation(operation 3 or 4), print the correct answer.
 

Sample Input
61 a1 b2 a2 c3481 a2 a2 a1 a31 b34
 

Sample Output
454511
 

Source
BestCoder Round #52 (div.1) ($)
 

Recommend
hujie   |   We have carefully selected several similar problems for you:  5426 5425 5424 5423 5422 

主要处理前后同时插入字符串较为麻烦。

这里维护两个值:当前插入形成的字符串的最长回文前缀,当前插入形成的字符串的最长回文后缀,我的代码里用last[0]和last[1]表示

每次向前插入时,通过最长回文前缀来寻找它的父亲,向后插入时,通过最长回文后缀来寻找它的父亲。


#include <iostream>#include <cstdio>#include <map>#include <cstring>#include <string>#include <queue>#define M 110#define N 150000using namespace std;class Node{public:    int next[30], pre, num, len, preNum;    void init(int _len)    {        memset(next, 0, sizeof next);        pre = 0;        num = 0;        len = _len;        preNum = 0;    }};Node node[N];class PaliTree{public:    int cnt, str[N*3], o, root0, root1, r, l, last[2];    long long paliSum;    int newNode(int _len)    {        node[++cnt].init(_len);        return cnt;    }    void init(int _n)    {        o = _n;        cnt = -1;        root0 = newNode(0);        root1 = newNode(-1);        last[0] = last[1] = root0;        l = o; r = o-1;        str[l-1] = str[r+1] = -1;        node[root0].pre = root1;        paliSum = 0;    }    int getFail(int p, int dir)    {        if(dir == 1)        {            for(; str[r-node[p].len-1] != str[r]; p = node[p].pre);        }        else        {            for(; str[l+node[p].len+1] != str[l]; p = node[p].pre);        }        return p;    }    void extend(char _ch, int dir) // dir 为0 向左插入    {        int ch = _ch-'a';        if(dir == 0)        {            str[--l] = ch;            str[l-1] = -1;        }        else        {            str[++r] = ch;            str[r+1] = -1;        }        int cur = getFail(last[dir], dir);        int nxt = node[cur].next[ch];        if(!nxt)        {            nxt = newNode(node[cur].len+2);            node[nxt].pre = node[getFail(node[cur].pre, dir)].next[ch];            node[nxt].preNum = node[node[nxt].pre].preNum+1;            node[cur].next[ch] = nxt;        }        last[dir] = nxt;        if(dir == 0 && l+node[nxt].len-1 == r)        {            last[dir^1] = nxt;        }        else if(dir == 1 && r-node[nxt].len+1 == l)        {            last[dir^1] = nxt;        }        node[nxt].num++;        paliSum += node[nxt].preNum;    }    int query1()    {        return cnt-1;    }    long long query2()    {        return paliSum;    }};PaliTree tree;int main(){//freopen("C:\\Users\\zfh\\Desktop\\in.txt", "r", stdin);    int q;    while(scanf("%d", &q) != -1)    {        int type;        char ch;        tree.init(150000);        for(int i = 0; i < q; i++)        {            scanf("%d", &type);            if(type == 1)            {                scanf(" %c", &ch);                tree.extend(ch, 0);            }            else if(type == 2)            {                scanf(" %c", &ch);                tree.extend(ch, 1);            }            else if(type == 3)            {                printf("%d\n", tree.query1());            }            else printf("%I64d\n", tree.query2());        }    }    return 0;}



0 0