码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5157 Harry and magic string【manacher】

时间:2018-11-20 15:12:14      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:select   ant   mes   stc   main   ase   ide   gic   chm   

Harry and magic string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 576    Accepted Submission(s): 287

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].

 

 

Output

For each test case, output one number in a line, indecates the answer.

 

 

Sample Input

aca aaaa

 

 

Sample Output

3 15

Hint

For 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

BestCoder Round #25

 

 

Recommend

heyang   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

 

 

题意:

在一个S串中找两个回文串,两个回文串没有重叠的部分。问有多少个这样的回文串对。

思路:

manacher我们可以求出以$i$为中心的回文串的个数。

$pre[i]$表示以$i$为开头的回文串的个数,$suf[i]$表示以$i$为结尾的回文串的个数。

那么我们要求的答案其实就是$\sum_{i = 1}^{len} pre[i] * (\sum_{j=1}^{i-1} suf[j])$

所以我们再用一个数组$sum$来存$suf$数组的前缀和。

那么$pre$和$suf$怎么求呢?

我们manacher处理出的$p[i] /2$表示的是以$i$为中心的回文的个数。

那么对于$i$之前的半径内的字符,他们的$pre$可以$+1$。同样他之后的半径内的字符,$suf$可以$-1$

暴力统计肯定是不行的,我们可以使用差分的思想。

对于$[i,j]$区间内的每一个数都更新$k$的话,我们可以用一个数组$add[i] += k$,add[j+1] -=k$

然后从前往后求前缀和得到的就是对区间的全部更新了。求$suf$和$pre$也是同样的道理。

$pre$是后面影响前面的所以从后往前求“#”向前靠,$suf$从前往后求“#”向后靠。

 

 1 #include<iostream>
 2 //#include<bits/stdc++.h>
 3 #include<cstdio>
 4 #include<cmath>
 5 //#include<cstdlib>
 6 #include<cstring>
 7 #include<algorithm>
 8 //#include<queue>
 9 #include<vector>
10 //#include<set>
11 //#include<climits>
12 //#include<map>
13 using namespace std;
14 typedef long long LL;
15 #define N 100010
16 #define pi 3.1415926535
17 #define inf 0x3f3f3f3f
18 
19 const int maxn = 1e5 + 5;
20 char s[maxn], ss[maxn * 2];
21 LL pre[maxn * 2], suf[maxn * 2], sum[maxn * 2];
22 int lens, p[maxn * 2];
23 
24 int init()
25 {
26     ss[0] = $;
27     ss[1] = #;
28     int lenss = 2;
29     for(int i = 0; i < lens; i++){
30         ss[lenss++] = s[i];
31         ss[lenss++] = #;
32     }
33     ss[lenss] = \0;
34     return lenss;
35 }
36 
37 void manacher()
38 {
39     int lenss = init();
40     int id, mx = 0;
41     for(int i = 1; i < lenss; i++){
42         if(i < mx){
43             p[i] = min(p[2 * id - i], mx - i);
44         }
45         else{
46             p[i] = 1;
47         }
48         while(ss[i - p[i]] == ss[i + p[i]])p[i]++;
49         if(mx < i + p[i]){
50             id = i;
51             mx = i + p[i];
52         }
53 
54     }
55 }
56 
57 int main()
58 {
59     while(scanf("%s", s) != EOF){
60         lens = strlen(s);
61         /*for(int i = 0; i < lens * 2 + 3; i++){
62             p[i] = 0;
63         }*/
64         for(int i = 0; i < lens + 1; i++){
65             suf[i] = pre[i] = sum[i] = 0;
66         }
67 
68         manacher();
69 
70         for(int i = 2; i <= lens * 2; i++){
71             int x = (i + 1) / 2;//向上取整
72             suf[x]++, suf[x + (p[i] / 2)]--;
73         }
74         for(int i = lens * 2; i >= 2; i--){
75             int x = i / 2;
76             pre[x]++, pre[x - (p[i] / 2)]--;
77         }
78 
79         for(int i = lens; i >= 1; i--){
80             pre[i] += pre[i + 1];
81         }
82         for(int i = 1; i <= lens; i++){
83             suf[i] += suf[i - 1];
84             sum[i] += sum[i - 1] + suf[i];
85         }
86         LL ans = 0;
87         for(int i = 1; i <= lens; i++){
88             ans += (LL)pre[i] * sum[i - 1];
89         }
90         printf("%I64d\n", ans);
91     }
92     return 0;
93 }

 

hdu5157 Harry and magic string【manacher】

标签:select   ant   mes   stc   main   ase   ide   gic   chm   

原文地址:https://www.cnblogs.com/wyboooo/p/9988397.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!