Harry and magic string
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 147 Accepted Submission(s): 72
Problem Description
Harry got a string T, he wanted to know the number of T’s disjoint palindrome substring pairs. A string is considered to be palindrome if and only if it reads the same backward or forward. For two substrings of
T:x=T[a1…b1],y=T[a2…b2]
(where a1 is the beginning index of
x,b1
is the ending index of x.
a2,b2
as the same of y), if both x and y are palindromes and
b1<a2 or b2<a1
then we consider (x, y) to be a disjoint palindrome substring pair of T.
Input
There are several cases.
For each test case, there is a string T in the first line, which is composed by lowercase characters. The length of T is in the range of [1,100000].
For each test case, there is a string T in the first line, which is composed by lowercase characters. The length of T is in the range of [1,100000].
Output
For each test case, output one number in a line, indecates the answer.
Sample Input
aca aaaa
Sample Output
3 15HintFor the first test case there are 4 palindrome substrings of T. They are: S1=T[0,0] S2=T[0,2] S3=T[1,1] S4=T[2,2] And there are 3 disjoint palindrome substring pairs. They are: (S1,S3) (S1,S4) (S3,S4). So the answer is 3.
Source
Recommend
反着构造一遍回文树,通过每个节点的后缀包含的回文串数目(称其为prenum值)求前缀和得到反向字符串的前i位包含的回文串数目,再正着构造一遍回文树,在用每个节点的prenum值乘上这个节点右侧的回文串数目,求和即可。
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <queue>
#define M 110
#define N 110000
using namespace std;
class Node
{
public:
int pre, next[30], len, prenum, num;
void setValue(int _len)
{
len = _len;
pre = 0;
memset(next, 0, sizeof next);
prenum = 0;
num = 0;
}
};
Node node[N];
char str[N], s[N];
int preNum[2][N];
long long preSum[N];
class PaliTree
{
public:
int cnt, root0, root1, last, n;
int newNode(int _len)
{
node[++cnt].setValue(_len);
return cnt;
}
void init()
{
cnt = -1; n = 0;
str[0] = -1;
root0 = newNode(0);
root1 = newNode(-1);
node[root0].pre = root1;
node[root1].pre = root0;
last = root0;
}
int nextNode(int p)
{
for(; str[n-node[p].len-1] != str[n]; p = node[p].pre);
return p;
}
void extend(char cc, int* a)
{
int ch = cc-'a';
str[++n] = ch;
int p = nextNode(last);
int nxt = node[p].next[ch];
if(!nxt)
{
nxt = newNode(node[p].len+2);
node[nxt].pre = node[nextNode(node[p].pre)].next[ch];
node[p].next[ch] = nxt;
node[nxt].prenum = node[node[nxt].pre].prenum+1;
}
last = nxt;
node[last].num++;
a[n] = node[last].prenum;
}
};
PaliTree tree;
int main()
{
//freopen("C:\\Users\\zfh\\Desktop\\in.txt", "r", stdin);
while(scanf(" %s", s) != -1)
{
tree.init();
int len = strlen(s);
for(int i = 0; i < len; i++)
{
tree.extend(s[i], preNum[0]);
}
tree.init();
for(int i = len-1; i >= 0; i--)
{
tree.extend(s[i], preNum[1]);
}
preSum[1] = preNum[1][1];
for(int i = 2; i <= len; i++)
{
preSum[i] = preSum[i-1]+preNum[1][i];
}
long long ans = 0;
for(int i = 1; i <= len; i++)
{
ans += preNum[0][i]*preSum[len-i];
}
printf("%I64d\n", ans);
}
return 0;
}