fork download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define itachi ios::sync_with_stdio(0); cin.tie(0);
  4.  
  5. struct Node {
  6. int nxt[26];
  7. int word;
  8. vector<int> pal;
  9. Node() {
  10. memset(nxt, -1, sizeof(nxt));
  11. word = -1;
  12. }
  13. };
  14.  
  15. const uint64_t base = 1315423911ull; // big base
  16. const uint64_t mod1 = 1000000007ull;
  17. const uint64_t p = 911382323ull; // random odd base
  18.  
  19. vector<uint64_t> pw; // powers of base
  20.  
  21. struct HString {
  22. string s;
  23. int n;
  24. vector<uint64_t> Hf, Hr;
  25.  
  26. void build(const string &t) {
  27. s = t;
  28. n = s.size();
  29. Hf.assign(n+1, 0);
  30. Hr.assign(n+1, 0);
  31.  
  32. for (int i = 0; i < n; ++i) {
  33. Hf[i+1] = Hf[i] * p + (s[i] + 1);
  34. Hr[i+1] = Hr[i] * p + (s[n-1-i] + 1);
  35. }
  36. }
  37.  
  38. // hash forward of s[l..r]
  39. uint64_t getF(int l, int r) const {
  40. return Hf[r+1] - Hf[l] * pw[r-l+1];
  41. }
  42.  
  43. // hash backward of s[l..r]
  44. uint64_t getR(int l, int r) const {
  45. // map s[l..r] to reversed index
  46. int rl = n-1-r;
  47. int rr = n-1-l;
  48. return Hr[rr+1] - Hr[rl] * pw[rr-rl+1];
  49. }
  50.  
  51. inline bool isPal(int l, int r) const {
  52. return getF(l, r) == getR(l, r);
  53. }
  54. };
  55.  
  56.  
  57. int main(){
  58. itachi;
  59. int n;
  60. cin >> n;
  61.  
  62. vector<string> a(n);
  63. long long total = 0;
  64. for(int i = 0; i < n; ++i){
  65. cin >> a[i];
  66. total += a[i].size();
  67. }
  68.  
  69. // Precompute powers
  70. pw.resize(total + 5);
  71. pw[0] = 1;
  72. for (int i = 1; i <= total; ++i)
  73. pw[i] = pw[i-1] * p;
  74.  
  75. // Build hash objects
  76. vector<HString> H(n);
  77. for (int i = 0; i < n; ++i)
  78. H[i].build(a[i]);
  79.  
  80. vector<Node> trie;
  81. trie.reserve(total + 5);
  82. trie.emplace_back(); // root = 0
  83.  
  84. // Insert reversed words
  85. for (int idx = 0; idx < n; ++idx) {
  86. const string &w = a[idx];
  87. int L = w.size();
  88. int node = 0;
  89.  
  90. for (int i = L - 1; i >= 0; --i) {
  91.  
  92. if (H[idx].isPal(0, i))
  93. trie[node].pal.push_back(idx);
  94.  
  95. int c = w[i] - 'a';
  96. if (trie[node].nxt[c] == -1) {
  97. trie[node].nxt[c] = trie.size();
  98. trie.emplace_back();
  99. }
  100. node = trie[node].nxt[c];
  101. }
  102.  
  103. trie[node].pal.push_back(idx);
  104. trie[node].word = idx;
  105. }
  106.  
  107. long long ans = 0;
  108.  
  109. // Searching
  110. for (int i = 0; i < n; ++i) {
  111. const string &w = a[i];
  112. int node = 0;
  113. int L = w.size();
  114.  
  115. for (int j = 0; j < L; ++j) {
  116.  
  117. if (trie[node].word != -1 && trie[node].word != i
  118. && H[i].isPal(j, L-1)) {
  119. ans++;
  120. }
  121.  
  122. int c = w[j] - 'a';
  123. if (trie[node].nxt[c] == -1) {
  124. node = -1;
  125. break;
  126. }
  127. node = trie[node].nxt[c];
  128. }
  129.  
  130. if (node != -1) {
  131. for (int idx : trie[node].pal) {
  132. if (idx != i)
  133. ans++;
  134. }
  135. }
  136. }
  137.  
  138. cout << ans << "\n";
  139. return 0;
  140. }
  141.  
Success #stdin #stdout 0.04s 5284KB
stdin
Standard input is empty
stdout
27441882