题解 P4503 【[CTSC2014]企鹅QQ】
serverkiller · · 题解
题意
给定
solution
没错 我又来卡空间了.在Mr_zherui的题解中 使用了两个数组来储存前后的hash值之和 但是我们其实可以利用前缀和来优化成一个数组qwq
基于上述的 我写了下面这份代码 利用的是进制hash 具体的看注释吧 最主要是在求相等的时候排序可以将复杂度从
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,l,s;
ll ha[30005][205],t[30005],Hina[205];//记得开longlong蛤
const int p = 2333;
int main()
{
scanf("%d%d%d",&n,&l,&s);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= l; j++)
{
char c;
cin >> c;//注意cin输入的时候是过滤换行符的 而scanf是读入换行符的 被这里卡着了
ha[i][j] = ha[i][j - 1] * p + c;
}
}
Hina[0] = 1;
for (int i = 1; i <= l; i++)
{
Hina[i] = Hina[i - 1] * p;
}//这里预处理出每一位的数量
int ans = 0;
for (int i = 1; i <= l; i++)
{
for (int j = 1; j <= n; j++)
{
t[j] = ha[j][l] - (ha[j][i] - ha[j][i - 1] * p) * Hina[l - i] - ha[j][i - 1] * (Hina[l - i + 1] - Hina[l - i]);
//去掉给第j个字符串第i位后的hash值 是整个的hash值 减掉这个位置的hash*Hina[l - i] 再减掉前面的数的hash*(Hina[l - i + 1]-Hina[l - i])
//其实可以去个括号就比较简洁了 但是我懒(
}
sort(t + 1,t + n + 1);//这里就是那个排序的地方啦
int tmp = 1;
for (int j = 1; j < n; j++)
{
if (t[j] != t[j + 1]) tmp = 1;
else
{
ans += tmp;
tmp++;
}
}
}
printf("%d\n",ans);//输出答案qwq
//system("pause");
return 0;
}
写完这个代码没完 我们注意到
因为这里进制hash去掉某一位的时候可以单单将那一位变成0而不需要将前面的数位后移 因此有了这个代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,l,s;
ll ha[30005],t[30005],Hina[205];
char c[300005][205];
const int p = 2333;
int main()
{
scanf("%d%d%d",&n,&l,&s);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= l; j++)
{
cin >> c[i][j];
ha[i] = ha[i] * p + c[i][j];
}
}
Hina[0] = 1;
for (int i = 1; i <= l; i++)
{
Hina[i] = Hina[i - 1] * p;
}
int ans = 0;
for (int i = 1; i <= l; i++)
{
for (int j = 1; j <= n; j++)
{
t[j] = ha[j] - c[j][i] * Hina[l - i];
}
sort(t + 1,t + n + 1);
int tmp = 1;
for (int j = 1; j < n; j++)
{
if (t[j] != t[j + 1]) tmp = 1;
else
{
ans += tmp;
tmp++;
}
}
}
printf("%d\n",ans);
//system("pause");
return 0;
}
这份代码的评测记录如下:
卡内存完毕x