YBT132 回文子串

传送门:YBT132 回文子串

样例输入

abcbabcbabcba
abacacbaaaab
END

样例输出

Case 1: 13 
Case 2: 6


题解

  该题解面向新手

  首先我们可以发现一个字符串的hash值和倒过来的hash值相等(也就是倒过来是同一个字符串), 那么他是回文的。

  那么现在问题来了,我们怎么找到最大的回文子串呢? 根据题目和数据范围容易发现使用二分答案。

  也就是说,二分最大长度,O(n)枚举是否存在(通过hash预处理)

  大概的思路有了, 但众所周知回文字符串分为奇串和偶串,也就是说不存长度为5的回文串时,可能还存在长度为6的。

  比如aaabaaa, 不存在长度为6,4的子串。读者仔细思考发现,答案不单调无法二分。

  但你想,事实上奇数和偶数长度分别都是单调的: 不存在长度为5的子串,就一定不存在长度为7, 9, 11、、、的子串回文, 偶数易燃。

  这就有很多处理方法了, 比如manache什么的, 不过这里讲一种麻烦但新手容易想到的方法

    奇偶串分别二分

  有点累,可以看看代码细节....

  宁还是别看了, 多组数据不清空....陆陆续续调了个好几天,实在看不了,抱歉,太累了没法改了

  

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string.h>
 4 #define ull unsigned long long
 5 using namespace std;
 6 
 7 const int N = 2000005;
 8 const ull b=231, p=233371;
 9 char s[N];
10 int len, T=0;
11 ull hash1[N], hash2[N], c[N];
12 
13 ull getHash1(int l, int r){
14     if(l == 0) return hash1[r];
15     return ((hash1[r] - hash1[l-1]*c[r-l+1]) );
16 }
17 
18 ull getHash2(int l, int r){
19     if(r == N) return hash2[r];
20     return ((hash2[l] - hash2[r+1]*c[r-l+1]) );
21 }
22 
23 int main(){
24     c[0]=1;
25     for(int i=1; i<N; i++) c[i] = (c[i-1]*b); 
26     while(++T){
27         for(int i=0; i<N; i++) s[i]=0, hash1[i] = hash2[i] = 0;
28         cin >> s;
29         if(!strcmp(s, "END")) return 0;
30         
31         len=strlen(s), hash1[0]=s[0], hash2[len-1]=s[len-1];
32         
33         for(int i=1; i<len; i++) hash1[i] = (hash1[i-1]*b + (ull)s[i]);
34         for(int i=len-2; i>=0; i--) hash2[i] = (hash2[i+1]*b + (ull)s[i]);
35         
36         int ans = 1, l=1, r=len;
37         while(l<r){
38             int mid = (l+r)/2, flag=1;
39             if(mid%2) mid++;
40             for(int i=0; i+mid-1<len; i++){
41                 if(getHash1(i, i+mid-1) == getHash2(i, i+mid-1)){
42                     flag=0;
43                     ans = mid;
44                     l = mid + 1;    
45                     break;                
46                 }
47             }
48             
49             if(flag) r = mid - 1;
50         }
51         
52         l=1, r=len;
53         while(l<r){
54             int mid = (l+r)/2, flag=1;
55             if((mid%2)==0) mid++;
56             for(int i=0; i+mid-1<len; i++){
57                 if(getHash1(i, i+mid-1) == getHash2(i, i+mid-1)){
58                     flag=0;
59                     ans = max(mid, ans);
60                     l = mid + 1;    
61                     break;                
62                 }
63             }
64             
65             if(flag) r = mid - 1;
66         }
67         
68         cout << "Case " << T << ": " << ans << endl;
69         
70     } 
71 }

  

 
原文地址:https://www.cnblogs.com/ltdjcoder/p/14559432.html