1. 程式人生 > >SPOJ-EPALIN 字符串哈希 回文

SPOJ-EPALIN 字符串哈希 回文

clu str 怎麽 回文串 else 字符串 turn char end

題意:給一個串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("\n"); 54 } 55 return 0; 56 }

SPOJ-EPALIN 字符串哈希 回文