Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.10 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <vector>
  4. #include <map>
  5. using namespace std;
  6.  
  7. typedef long long int64;
  8.  
  9. const int kSigma = 27;
  10.  
  11. struct RollingHash {
  12.     static const int kMods[];
  13.     static const int kNumMods = 2;
  14.    
  15.     int normal[kNumMods]; // left to right
  16.     int reversed[kNumMods]; // right to left
  17.     int sig_exp[kNumMods];
  18.    
  19.     RollingHash() {
  20.         for (int i = 0; i < kNumMods; i += 1) {
  21.             normal[i] = reversed[i] = 0;
  22.             sig_exp[i] = 1;
  23.         }
  24.     }
  25.  
  26.     void AddLeft(char c) {
  27.         for (int i = 0; i < kNumMods; i += 1) {
  28.             int kMod = kMods[i];
  29.             reversed[i] = (1LL * reversed[i] * kSigma + c - 'a' + 1) % kMod;
  30.             normal[i] = (normal[i] + 1LL * sig_exp[i] * (c - 'a' + 1)) % kMod;          
  31.             sig_exp[i] = (1LL * sig_exp[i] * kSigma) % kMod;
  32.         }
  33.  
  34.     }
  35.  
  36.     void AddRight(char c) {
  37.         for (int i = 0; i < kNumMods; i += 1) {
  38.             int kMod = kMods[i];      
  39.             normal[i] = (1LL * normal[i] * kSigma + c - 'a' + 1) % kMod;
  40.             reversed[i] = (reversed[i] + 1LL * sig_exp[i] * (c - 'a' + 1)) % kMod;
  41.             sig_exp[i] = (1LL * sig_exp[i] * kSigma) % kMod;
  42.         }
  43.     }
  44.  
  45.     RollingHash ReverseHash() {
  46.         RollingHash r = *this;
  47.         for (int i = 0; i < kNumMods; i += 1) {
  48.             swap(r.normal[i], r.reversed[i]);
  49.         }
  50.         return r;
  51.     }
  52.  
  53.     bool IsPalindrome() {
  54.         bool ok = true;
  55.         for (int i = 0; i < kNumMods; i += 1) {
  56.             ok &= normal[i] == reversed[i];
  57.         }
  58.         return ok;
  59.     }
  60.  
  61.     bool operator<(const RollingHash& rhs) const {
  62.         for (int i = 0; i < kNumMods; i += 1) {
  63.             if (rhs.normal[i] != normal[i]) {
  64.                 return normal[i] < rhs.normal[i];
  65.             }
  66.         }
  67.         return false;
  68.     }
  69. };
  70.  
  71. const int RollingHash::kMods[] = {(int)1e9+7, (int)1e9+9};
  72.  
  73. map<RollingHash, int> palindroms_from_here, reversed_full_word;
  74.  
  75. int main() {
  76.     int n; cin >> n;
  77.     vector<string> all_words(n);
  78.     for (int i = 0; i < n; i += 1) {
  79.         cin >> all_words[i];
  80.     }
  81.  
  82.     for (const string& word : all_words) {
  83.         int l = (int)word.size();
  84.         vector<bool> is_poli(l + 1, false);
  85.         {
  86.             RollingHash a;
  87.             for (int i = l; i >= 0; i -= 1) {
  88.                 if (a.IsPalindrome()) {
  89.                     is_poli[i] = true;
  90.                 }
  91.                 if (i != 0) {
  92.                     a.AddLeft(word[i - 1]);
  93.                 }
  94.             }
  95.         }
  96.  
  97.         vector<RollingHash> left_reversed_hash;
  98.         {
  99.             RollingHash b;
  100.             for (int i = 0; i <= l; i += 1) {
  101.                 left_reversed_hash.push_back(b.ReverseHash());
  102.                 if (i != l) {
  103.                     b.AddRight(word[i]);
  104.                 }
  105.             }
  106.  
  107.             reversed_full_word[b.ReverseHash()] += 1;
  108.         }
  109.  
  110.         for (int i = 0; i <= l; i += 1) {
  111.             if (is_poli[i]) {
  112.                 palindroms_from_here[left_reversed_hash[i]]+= 1;
  113.             }
  114.         }
  115.     }
  116.  
  117.     int64 result = 0;
  118.     for (auto word : all_words) {
  119.         RollingHash a, b;
  120.         vector<RollingHash> front(word.size() + 1);
  121.         vector<RollingHash> back(word.size() + 1);
  122.         for (int i = 0; i <= (int)word.size(); i += 1) {
  123.             front[i] = a;
  124.             if (i != (int)word.size()) {
  125.                 a.AddRight(word[i]);
  126.             }
  127.         }
  128.  
  129.         for (int i = (int)word.size(); i >= 0; i -= 1) {
  130.             back[i] = b;
  131.             if (i != 0) {
  132.                 b.AddLeft(word[i - 1]);
  133.             }
  134.         }
  135.  
  136.         for (int i = 0; i <= (int)word.size(); i += 1) {
  137.             if (front[i].IsPalindrome()) {
  138.                 result += reversed_full_word[back[i]];
  139.             }
  140.         }
  141.  
  142.         result -= reversed_full_word[a]; // equal words
  143.         result += palindroms_from_here[a]; // our word is on the right without having the big part
  144.  
  145.         if (a.IsPalindrome()) {
  146.             result -= 1;
  147.         }
  148.     }
  149.  
  150.     cout << result << '\n';
  151.     return 0;
  152. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement