zoukankan      html  css  js  c++  java
  • 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 }
    
    
  • 相关阅读:
    Chrome开发者工具中Elements(元素)断点的用途
    最简单的SAP云平台开发教程
    Java实现 LeetCode 495 提莫攻击
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 494 目标和
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 493 翻转对
    Java实现 LeetCode 492 构造矩形
  • 原文地址:https://www.cnblogs.com/flyljz/p/11648989.html
Copyright © 2011-2022 走看看