• acwing 139. 回文子串的最大长度


    题面:

    如果一个字符串正着读和倒着读是一样的,则称它是回文的。

    给定一个长度为N的字符串S,求他的最长回文子串的长度是多少。

    输入格式

    输入将包含最多30个测试用例,每个测试用例占一行,以最多1000000个小写字符的形式给出。

    输入以一个以字符串“END”(不包括引号)开头的行表示输入终止。

    输出格式

    对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。

    每个输出占一行。

    输入样例:

    abcbabcbabcba
    abacacbaaaab
    END
    

    输出样例:

    Case 1: 13
    Case 2: 6
    题解:
    马拉车的模板题,这题用字符哈希偏复杂:

    Manacher算法,但是我们这道题目是锻炼我们的哈希水平,所以我们这里只说如何用哈希算法求解.作者忘记如何使用马拉车算法了…
    上一道兔子兔子兔子的题目,我们知道判断两个字符串是否相等,可以使用字符串哈希,也就是将字符串算成P进制数值,然后区间和判断即可,那么这道题目我们需要一个正的字符串,还需要一个反的字符串,然后如果正字符串等于反的字符串,那么奇数回文串就2+1,偶数回文串就直接2即可.之所以要这么做,因为我们是要回文对不对,我们需要将回文拆解成为一个正字符串和一个反字符串,这样才好处理这道题目.
    既然如此,我们可以算出一个前缀和,再算出一个后缀和,然后就可以知道,正字符串和一个反字符串.字符串的哈希值就是这个区间的哈希值和.
    算完之后,我们当前就只需要枚举一个mid中间点,因为所有回文串都是有一个中间点(奇),或者中间区间(偶),然后二分分别寻找这个字符串长度即可,记住不是回文串,回文串的长度,是字符串长度* 2 + 1(奇) 或者是字符串长度 * 2(偶数).
    切记如果说这个最大回文串为1(也就是所有字符都不一样,比如说abcdefg),那么输出是1,不是3,奇数回文串=奇数字符串*2+1,你们要小心特判这种情况,或者处理二分边界.

    作者:秦淮岸灯火阑珊
    链接:https://www.acwing.com/solution/acwing/content/906/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。(搬运的题解)

    代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 using namespace std;
     6 #define ull unsigned long long
     7 ull p[2000010],hl[2000010],hr[2000010];//hl数组存从左到右,hr反之
     8 char str[2000010];
     9 const int base=131;
    10 ull get(ull h[],int l,int r)
    11 {
    12     return h[r]-h[l-1]*p[r-l+1];
    13 }
    14 int main()
    15 {
    16     int t=1;
    17     while(scanf("%s",str+1))
    18     {
    19         if (strcmp(str+1,"END")==0) //结束读入
    20             return 0;
    21     p[0]=1;
    22     int len=strlen(str+1);
    23     for(int i=len*2;i>0;i-=2)
    24     {
    25         str[i]=str[i/2];
    26         str[i-1]='z'+1;
    27     }
    28     len*=2;
    29     str[++len]='z'+1;
    30     for(int i=1,j=len;i<=len;i++,j--)
    31     {
    32         hl[i]=hl[i-1]*base+str[i]-'a'+1;
    33         hr[i]=hr[i-1]*base+str[j]-'a'+1;
    34         p[i]=p[i-1]*base;
    35     }
    36     
    37      int res=0;
    38      for(int i=1;i<=len;i++)
    39      {
    40          int l=0,r=min(i-1,len-i);
    41          while(l<r)//二分回文长度
    42          {
    43              int mid=(l + r + 1) >> 1;
    44              if(get(hl,i-mid,i-1)!=get(hr,len-(i+mid)+1,len-(i+1)+1))r=mid-1;//
    45              else
    46              l=mid;
    47          }
    48          if(str[i-l]<='z') res=max(res,l+1);//如果最后一位是字母则(2*l+1)向上取整
    49          else
    50          res=max(res,l);
    51      }
    52      printf("Case %d: %d
    ",t++,res);
    53     }
    54     return 0;
    55 }
    
    
  • 相关阅读:
    20170417成员运算符、身份运算符、布尔运算符
    20170417学习find、replace、abs三个函数
    shell 双中括号 双小括号
    man 命令
    awk 命令-对文本和数据进行处理
    shell-1-day
    shell---0-day
    /etc
    Selenium IDE使用
    python 自动化测试框架 pytest 和unittest 的区别
  • 原文地址:https://www.cnblogs.com/flyljz/p/11648989.html
Copyright © 2020-2023  润新知