UVA 257 Palinwords(hash)题解
思路:给你字符串,如果他包含至少两个长度大于等于3的回文,并且这些回文不能嵌套(例如aaa嵌套在aaaa,waw嵌套在awawa),如果这个字符串这么牛逼的话,就输出他。
思路:拿到字符串先正序hash和逆序hash,用来判断回文串。这里其实只要判断长度为3和4的回文就行,因为3,4大的可以嵌套在比他大的里面。一开始我还在想怎么区分aaa和aaaa,弄了个很复杂的东西,但是我发现其实只要储存回文串的半径的hash就行了!这样长度3和4也能比了。
代码:
#include<stack> #include<vector> #include<queue> #include<set> #include<cstring> #include<string> #include<sstream> #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #define ll long long #define ull unsigned long long using namespace std; const int maxn = 255+10; const int seed = 131; const int MOD = 100013; const int INF = 0x3f3f3f3f; char s[maxn]; ull ha[2][maxn],bin[maxn]; void init(){ bin[0] = 1; for(int i = 1; i <= 255; i++) bin[i] = bin[i - 1] * seed; } void HASH(int len){ ha[0][0] = 0; for(int i = 1; i <= len; i++) //顺序 ha[0][i] = ha[0][i - 1] * seed + s[i]; ha[1][0] = 0; for(int i = len,j = 1; i >= 1; i--, j++) //逆序 ha[1][j] = ha[1][j - 1] * seed + s[i]; } ull getsub(int l,int r,int id){ return ha[id][r] - ha[id][l - 1] * bin[r - l + 1]; } int main(){ init(); while(scanf("%s", s + 1) != EOF){ int len = strlen(s + 1); HASH(len); int flag = -1; ull is; for(int i = 1; i <= len - 2; i++){ ull suf = getsub(i, i + 1,0); //顺序 ull pre = getsub(len - (i + 2) + 1, len - (i + 1) + 1, 1); //逆序 if(suf == pre){ if(flag == -1){ is = suf; flag = 0; } else if(suf != is){ flag = -2; break; } } } if(flag == -2){ printf("%s\n", s + 1); continue; } for(int i = 1; i<= len - 3; i++){ ull suf = getsub(i, i + 1,0); //顺序 ull pre = getsub(len - (i + 3) + 1, len - (i + 2) + 1, 1); //逆序 if(suf == pre){ if(flag == -1){ is = suf; flag = 0; } else if(suf != is){ flag = -2; break; } } } if(flag == -2){ printf("%s\n", s + 1); continue; } } return 0; }