分析：

$s_i,s_j$的长度分别为$L_i, L_j$，一共有如下三种情况：

• $L_i=L_j$，那么有$s_i$等于$s_j$的反串，$s_i,s_j$构成回文串，注意$s_i$本身是回文串的情况，需要从答案中减去
• $L_i > L_j$，那么有$s_i$的某个后缀是回文串，并且$s_j$是剩余部分的反串
• $L_i < L_j$，分析方法同上

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
#define REP(i, a, b) for(int i = a; i < b; i++)
#define PER(i, a, b) for(int i = b - 1; i >= a; i--)

typedef long long LL;

const int maxn = 100000 + 10;
const int MOD[2] = { 1000000007, 1000000009 };

int n;

struct Hash {
int h[2];
Hash(int h0 = 0, int h1 = 0) { h[0] = h0; h[1] = h1; }
Hash(char c) { h[0] = c-'a'+1; h[1] = c-'a'+1; }
bool operator < (const Hash& t) const {
return h[0] < t.h[0] || (h[0] == t.h[0] && h[1] < t.h[1]);
}
Hash operator * (const Hash& t) const {
return Hash(1LL * t.h[0] * h[0] % MOD[0], 1LL * t.h[1] * h[1] % MOD[1]);
}
Hash operator + (const Hash& t) const {
return Hash((h[0] + t.h[0]) % MOD[0], (h[1] + t.h[1]) % MOD[1]);
}
bool operator == (const Hash& t) const {
return h[0] == t.h[0] && h[1] == t.h[1];
}
void debug() { printf("{ %d, %d }\n", h[0], h[1]); }
};

Hash p(1, 1);
const Hash base(27, 27);

Hash addLeft(const Hash& a, char c) {
return (Hash(c) * p) + a;
}

Hash addRight(const Hash& a, char c) {
return (a * base) + Hash(c);
}

vector<string> s;
map<Hash, int> Normal, Reverse;
vector<Hash> preNormal[maxn], preReverse[maxn], sufNormal[maxn], sufReverse[maxn];

int main() {
scanf("%d", &n); s.resize(n);
REP(i, 0, n) {
cin >> s[i];
int l = s[i].length();

p = Hash(1, 1);
preNormal[i].emplace_back(0, 0);
preReverse[i].emplace_back(0, 0);
REP(j, 0, l) {
p = p * base;
}

p = Hash(1, 1);
sufNormal[i].resize(l + 1);
sufReverse[i].resize(l + 1);
sufNormal[i][l] = sufReverse[i][l] = Hash(0, 0);
PER(j, 0, l) {
p = p * base;
}
Normal[preNormal[i][l]]++;
Reverse[preReverse[i][l]]++;
}

LL ans = 0;
REP(i, 0, n) {
int l = s[i].length();

//case 1
if(Reverse.count(preNormal[i][l]))
ans += Reverse[preNormal[i][l]];
if(preNormal[i][l] == preReverse[i][l]) ans--;

//case 2
PER(j, 1, l) if(sufNormal[i][j] == sufReverse[i][j]) {
if(Reverse.count(preNormal[i][j]))
ans += Reverse[preNormal[i][j]];
}

//case 3
REP(j, 1, l) if(preNormal[i][j] == preReverse[i][j]) {
if(Normal.count(sufReverse[i][j]))
ans += Normal[sufReverse[i][j]];
}
}

cout << ans << endl;

return 0;
}

posted @ 2017-03-24 21:21  AOQNRMGYXLMV  阅读(...)  评论(...编辑  收藏