SPOJ-EPALIN 字符串哈希 回文

题意:给一个串s,用最少的字母补全使它成为回文串

思路:先求正反两个哈希,然后枚举终点

思维上没什么难度主要是细节以及怎么写比较自然

我选择把两个哈希串都弄成递增的,那原串s[l..r]的哈希值就是反哈希[n-r, n-l]的值

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #define LL long long
 6 #define uLL unsigned long long
 7 #define debug(x) cout << "[" << x << "]" << endl
 8 using namespace std;
 9 
10 const int mx = 1e5+10;
11 const int base = 131;
12 uLL hs[mx], ht[mx], p[mx];
13 char s[mx];
14 
15 int main(){
16     p[0] = 1;
17     for (int i = 1; i < mx; i++) p[i] = p[i-1]*base;
18     while (scanf("%s", s+1) == 1){
19         int n = strlen(s+1), flag = -1;
20         for (int i = 1; i <= n; i++) {
21             hs[i] = hs[i-1]*base+s[i]-'a';
22             ht[i] = ht[i-1]*base+s[n-i+1]-'a';
23         }
24         int i = n/2+1;
25         while (i <= n){
26             uLL a = hs[n]-p[n-i+1]*hs[i-1];
27             uLL b = ht[2*n-2*i+2]-p[n-i+1]*ht[n-i+1];
28             if (2*i-n >= 0 && a == b){
29                 flag = 0;
30                 break;
31             }
32             a = hs[n]-p[n-i]*hs[i];
33             b = ht[2*n-2*i+1]-p[n-i]*ht[n-i+1];
34             if (i+1 <= n && a == b) {
35                 flag = 1;
36                 break;
37             }
38             i++;
39         }
40         printf("%s", s+1);
41         if (flag == 1){
42             for (int j = 2*i-n-1; j >= 1; j--)
43                 printf("%c", s[j]);
44         }
45         else if (!flag){
46             for (int j = 2*i-n-2; j >= 1; j--)
47                 printf("%c", s[j]);
48         }
49         else {
50             for (int j = n-1; j >= 1; j--)
51                 printf("%c", s[j]);
52         }
53         printf("
");
54     }
55     return 0;
56 }
原文地址:https://www.cnblogs.com/QAQorz/p/9733952.html