zoukankan      html  css  js  c++  java
  • hdu5157 Harry and magic string【manacher】

    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] = '';
    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
    ", ans);
    91     }
    92     return 0;
    93 }
  • 相关阅读:
    说一说javascript的异步编程
    Flink 整合 Nacos,让 Flink 作业配置动态更新不再是难事
    Flink 整合 Apollo,动态更新 Flink 作业配置
    一文让你彻底了解大数据实时计算引擎 Flink
    《大数据实时计算引擎 Flink 实战与性能优化》新专栏
    滴滴实时计算发展之路及平台架构实践
    Flink 从 0 到 1 学习 —— Flink Data transformation(转换)
    Flink Connector 深度解析
    Flink 从 0 到 1 学习 —— Flink 配置文件详解
    vue-cli3如何配置 eslint 及配合 vscode 自动保存
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9988397.html
Copyright © 2011-2022 走看看