【洛谷P4503】【CTSC2014】企鹅QQ

YzNZDRp1.png (1364×2656)

【洛谷P4503】【CTSC2014】企鹅QQ

题目背景

PenguinQQ 是中国最大、最具影响力的 SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志、群、即时通讯、相册、集市等丰富强大的互联网功能体验,满足用户对社交、资讯、娱乐、交易等多方面的需求。

题目描述

小Q 是 PenguinQQ 网站的管理员,他最近在进行一项有趣的研究——哪些账户是同一个人注册的。经过长时间的分析,小Q 发现同一个人注册的账户名称总是很相似的,例如 Penguin1Penguin2Penguin3 ……于是 小Q 决定先对这种相似的情形进行统计。
小Q 定义,若两个账户名称是相似的,当且仅当这两个字符串等长且恰好只有一位不同。例如 “Penguin1” 和 “Penguin2” 是相似的,但 “Penguin1” 和 “2Penguin” 不是相似的。而 小Q 想知道,在给定的 n 个账户名称中,有多少对是相似的。
为了简化你的工作,小Q 给你的 N 个字符串长度均等于 L ,且只包含大小写字母、数字、下划线以及 ‘@’ 共64种字符,而且不存在两个相同的账户名称。

输入格式

第一行包含三个正整数 N ,L ,S 。其中 N 表示账户名称数量,L 表示账户名称长度,S 用来表示字符集规模大小,它的值只可能为 2 或 64。
若 S 等于 2,账户名称中只包含字符 ‘0’ 和 ‘1’ 共2种字符;
若 S 等于 64,账户名称中可能包含大小写字母、数字、下划线以及 ‘@’ 共64种字符。
随后 N 行,每行一个长度为 L 的字符串,用来描述一个账户名称。数据保证 N个字符串是两两不同的。

输出格式

仅一行一个正整数,表示共有多少对相似的账户名称。

输入输出样例

输入 #1

4 3 64
Fax
fax
max
mac

输出 #1

4

说明/提示

4对相似的字符串分别为:Fax 与 fax,Fax 与 max,fax 与 max,max 与 mac。
测试点编号NLS
1501064
250010064
330001002
4300010064
530000502
6300005064
7300002002
83000020064
9300002002
103000020064
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")

#include "bits/stdc++.h"

#define mem(x) memset((x), 0, sizeof((x)))
#define il __attribute__((always_inline))

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#if __cplusplus > 201403L
#define r
#else
#define r register
#endif

#define c const

namespace _c
{
c double pi = acos(-1.0);
namespace min
{
c int i8 = -128;
c int i16 = -32768;
c int i = -2147483647 - 1;
c ll l = -9223372036854775807LL - 1;
} // namespace min

namespace max
{
c int i8 = 127;
c int i16 = 32767;
c int i = 2147483647;
c ll l = 9223372036854775807LL;
} // namespace max
} // namespace _c

namespace _f
{
template <typename T>
inline c T gcd(T m, T n)
{
    while (n != 0)
    {
        T t = m % n;
        m = n;
        n = t;
    }
    return m;
}

template <typename T>
inline c T abs(c T &a)
{
    return a > 0 ? a : -a;
}

template <typename T>
inline T pow(T a, T b)
{
    T res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = res * a;
        }
        a = a * a;
        b >>= 1;
    }
    return res;
}

template <typename T>
inline T pow(T a, T b, c T &m)
{
    a %= m;
    T res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = res * a % m;
        }
        a = a * a % m;
        b >>= 1;
    }
    return res % m;
}
} // namespace _f

namespace io
{
template <typename T>
inline T read()
{
    r T res = 0, neg = 1;
    char g = getchar();
    for (; !isdigit(g); g = getchar())
    {
        if (g == '-')
        {
            neg = -1;
        }
    }
    for (; isdigit(g); g = getchar())
    {
        res = res * 10 + g - '0';
    }
    return res * neg;
}
template <typename T>
inline void read(T &t)
{
    t = read<T>();
}
template <typename T>
inline void readln(c T first, c T last)
{
    for (r T it = first; it != last; it++)
    {
        read(*it);
    }
}

template <typename T>
inline void _write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9)
    {
        _write(x / 10);
    }
    putchar(x % 10 + '0');
}
template <typename T>
inline void write(c T &x, c char &sep = ' ')
{
    _write(x);
    putchar(sep);
}
template <typename T>
inline void writeln(c T &x)
{
    write(x, '\n');
}
template <typename T>
inline void writeln(c T first, c T last, c char &sep = ' ', c char &ends = '\n')
{
    for (r T it = first; it != last; it++)
    {
        write(*it, sep);
    }
    putchar(ends);
}

#if __cplusplus >= 201103L
template <typename T, typename... Args>
void read(T &x, Args &... args)
{
    read(x);
    read(args...);
}
#endif
} // namespace io
#undef c
#undef r

const int N = 30000 + 5;
const int L = 200 + 5;

const int MOD_1 = 149;
const int MOD_2 = 137;
const int MOD_3 = 233;
const int MOD_4 = 213;

int n, l, s;
int ans = 0;
char str[L];

ull t[N], bf[N][L], bh[N][L];

inline void proc(int x)
{
    for (register int i = 1; i <= l; i++)
    {
        bf[x][i] = bf[x][i - 1] * MOD_1 + str[i];
    }
    for (register int i = l; i >= 1; i--)
    {
        bh[x][i] = bh[x][i + 1] * MOD_2 + str[i];
    }
}

int main()
{
    io::read(n, l, s);

    for (register int i = 1; i <= n; i++)
    {
        scanf("%s", str + 1);
        proc(i);
    }

    for (register int i = 1, j, now = 1; i <= l; i++, now = 1)
    {
        for (j = 1; j <= n; j++)
        {
            t[j] = bf[j][i - 1] * MOD_3 + bh[j][i + 1] * MOD_4;
        }
        sort(t + 1, t + n + 1);

        for (j = 2; j <= n; j++)
        {
            if (t[j] == t[j - 1])
            {
                ans += now;
                now++;
            }
            else
            {
                now = 1;
            }
        }
    }

    io::writeln(ans);
}

评论

发表评论

此博客中的热门博文

高中地理必修一知识点总结

【CF961F】k-substrings

偷税与漏税的区别