Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- int n;
- typedef long long ll;
- const int MX=1e5+6,MD=1e8+7;
- char bb[MX];
- map<ll,ll> Rev,For;
- #define f first
- #define s second
- class Hash
- {
- ll b, Md,hsh,sb;
- public:
- Hash() {}
- Hash(int x,int y)
- {
- Md=x,b=y;
- hsh=0;
- sb=1;
- }
- ll insert(char c)
- {
- ll x = c - 'a' +1;
- hsh+=sb*x;
- hsh%=Md;
- sb*=b;
- sb%=Md;
- return hsh;
- }
- };
- pair<ll,ll> CumHash[MX];
- ll dp[MX],Nigf[MX],Nigr[MX];
- vector<ll> Zz[MX][2];
- void doit(int sz,bool flag,int ij)
- {
- Hash Make1(1e8+7,33);
- Hash Make2(1e8+7,33);
- for(int i=0; i<sz; i++)
- {
- CumHash[i+1].f = Make1.insert(bb[i]);
- CumHash[sz-i].s= Make2.insert(bb[sz-1-i]);
- }
- CumHash[0]=CumHash[sz+1]={0,0};
- for(int i=sz+1; i<=2*sz; i++)
- {
- if(i%2)
- {
- int s = i/2,l= sz - i/2 -1 /*Here*/, beg= i/2 + 2;
- ll hsh1 = CumHash[s].f - CumHash[s - l].f;
- ll hsh2 = CumHash[beg].s;
- hsh1=(hsh1+MD)%MD;
- hsh2=(hsh2+MD)%MD;
- hsh2*=dp[s-l];
- hsh2%=MD;
- if(hsh1==hsh2)
- {
- //cout<<s<<' '<<l<< ':'<<endl;
- Zz[ij][flag].push_back(CumHash[s - l].f);
- }
- }
- else
- {
- int s = i/2,l= sz - i/2 /*Here*/, beg= i/2;
- ll hsh1 = CumHash[s].f - CumHash[s - l].f;
- ll hsh2 = CumHash[beg+1].s;
- hsh1=(hsh1+MD)%MD;
- hsh2=(hsh2+MD)%MD;
- hsh2*=dp[s-l];
- hsh2%=MD;
- if(hsh1==hsh2)
- {
- // cout<<l<<' '<<s<<endl;
- assert(s-l==i-sz);
- Zz[ij][flag].push_back(CumHash[s-l].f);
- }
- }
- }
- }
- vector<int> Vv[MX];
- int main()
- {
- ll ans=0,vb=1;
- cin>>n;
- for(int i=0; i<MX-2; i++)
- {
- dp[i]=vb;
- vb*=33;
- vb%=MD;
- }
- for(int ij=0; ij<n; ij++)
- {
- scanf("%s",bb);
- int sz=strlen(bb);
- Vv[sz].push_back(ij);
- doit(sz,0,ij);
- Nigf[ij]=CumHash[sz].f;
- //return 0;
- reverse(bb,bb+sz);
- doit(sz,1,ij);
- Nigr[ij]=CumHash[sz].f;
- /*for(auto u : Zz[ij][0])
- cout<<u<<' ';
- cout<<endl;*/
- }
- for(int ix=0; ix<MX; ix++)
- {
- if(Vv[ix].empty())continue;
- /* for(auto u : Vv[ix])
- {
- Rev[Nigr[u]]++;
- For[Nigf[u]]++;
- }*/
- for(auto u : Vv[ix])
- {
- /*Rev[Nigr[u]]--;
- For[Nigf[u]]--;*/
- int i = u;
- for(auto u : Zz[i][0])
- ans+=Rev[u];
- for(auto u : Zz[i][1])
- ans+=For[u];
- Rev[Nigr[i]]++;
- For[Nigf[i]]++;
- }
- }
- cout<<ans;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement