Moca的生日快到了,她的朋友Ran要去Yamabuki面包店为她订生日蛋糕。山步面包店提供n种蛋糕。冉然知道Moca是山步面包房的1号粉,吃得又多,所以她打算订两个蛋糕,放在一起做成一个大蛋糕。山步烘焙坊制作的蛋糕可以由小写拉丁字母组成的字符串组成,这些字母描述了蛋糕上的配料,如草莓和巧克力。把两个蛋糕放在一起是两个对应的字符串的连接。例如,将cake ab和cake cabc放在一起的结果是一个大的cake abcabc。为了更容易分享蛋糕,冉然会选择两块蛋糕,把它们放在一起做成一个大蛋糕,这个蛋糕可以被分成两半,分成两片相同的蛋糕。例如,蛋糕abcabc将被分成两块蛋糕abc,而蛋糕abbc将被分成两块不同的蛋糕ab和bc。注意冉不能反转蛋糕,这意味着蛋糕abba会被分成两个不同的蛋糕ab和ba。你能帮冉然算出满足上述条件的蛋糕有多少对吗?输入第一行包含一个整数n(1≤n≤4·105)-蛋糕的数量。接下来的n行描述了所有的蛋糕,其中第i行包含一个由小写拉丁字母组成的字符串si(1≤|sil≤4·105)。保证蛋糕长度之和不超过4 - 105。
Sample 1
Inputcopy | Outputcopy |
---|---|
3 ab ab cabc | 3 |
Sample 2
Inputcopy | Outputcopy |
---|---|
3 abc a cabc | 0 |
Sample 3
Inputcopy | Outputcopy |
---|---|
4 hhh hhh hhh hhh | 6 |
题解:
本题思路并不算难,从小到大,处理每个串的哈希值
看串的前缀与后缀是否相等,如果相等,看前缀与后缀间的值是否出现过,出现过加上即可
还要判断整个是否出现过,加上出现过的次数
然后记录一整个串的值++
但是这题的坑点就是,单hash记录的值可能会被卡,所以要用双hash
(如果遇到确定时hash的题,如果单hash过不了,可以试试双hash)
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
using namespace std;
#define int long long
const int N = 4e6 + 10;
typedef pair<int, int> PII;
unsigned long long seed;
string ss[N];
int hs1[N],hs2[N],p1[N],p2[N];
int x = 133331;
char s[N];
map<PII,int> cnt;
bool cmp(string a,string b)
{
return a.size() < b .size();
}
int mod1 = 1e9 + 7,mod2 = 1e9 + 11;
int get1(int l,int r)
{
if(l > r)
return 0;
return (hs1[r] - hs1[l-1]*p1[r-l+1]%mod1 + mod1)%mod1;
}
int get2(int l,int r)
{
if(l > r)
return 0;
return (hs2[r] - hs2[l-1]*p2[r-l+1]%mod2 + mod2)%mod2;
}
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> ss[i];
}
p1[0] = 1,p2[0] = 1;
sort(ss+1,ss+1+n,cmp);
for(int i = 1;i <= 4e5;i++)
{
p1[i] = p1[i-1]*x%mod1;
p2[i] = p2[i-1]*x%mod2;
}
int ans = 0;
for(int i = 1;i <= n;i++)
{
int len = ss[i].size();
for(int j = 1;j <= len;j++)
s[j] = ss[i][j-1];
hs1[0] = 0;
hs2[0] = 0;
for(int j = 1;j <= len;j++)
{
hs1[j] = (hs1[j-1]*x%mod1 + s[j])%mod1;
hs2[j] = (hs2[j-1]*x%mod2 + s[j])%mod2;
}
for(int j = 1;j <= len - j + 1;j++)
{
int r = len - j + 1;
if(get1(1,j) == get1(r,len)&&get2(1,j) == get2(r,len))
{
int t1 = get1(j + 1,r - 1);
int t2 = get2(j + 1,r - 1);
ans += cnt[{t1,t2}];
}
}
ans += cnt[{get1(1,len),get2(1,len)}];
cnt[{get1(1,len),get2(1,len)}]++;
}
cout << ans;
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
//scanf("%lld",&t);
while (t--)
{
solve();
}
}
//3 F
//5 B
//6 F
//9 F
//10 B
//12 F
//15 FB
//18 FB