【题解】字符串匹配

题目描述

  给定N个字符串(第i个字符串长度为Mi,字符串内包含数字、大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串。

输入输出格式

输入格式

  第一行包含一个整数N,为字符串的个数。

  接下来N行每行包含一个字符串,为所提供的字符串。

输出格式

  输出包含一行,包含一个整数,为不同的字符串个数。

输入输出样例

输入样例

5

abc

aaaa

abc

abcc

12345

输出样例

4

说明

数据规模:

  对于30%的数据:N<=10,Mi≈6,Mmax<=15;

  对于70%的数据:N<=1000,Mi≈100,Mmax<=150

  对于100%的数据:N<=10000,Mi≈1000,Mmax<=1500

样例说明:

  样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。

题解

  字符串匹配,明显就是字符串hash的裸题。

  最初本来是想用map来装hash值来判断是否有重复,但实际上不同那么麻烦,只需要按照hash值排序一下,然后直接遍历一遍序列就行了。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

#define MAX_N 10000
#define MAX_M 1500

using namespace std;

int n;
struct String
{
    char str[MAX_M | 1];
    int len;
    unsigned long long hash;
    friend bool operator < (String x, String y)
    {
        return x.hash < y.hash;
    }
}a[MAX_N | 1];

inline int Insert(char s[], int len)
{
    unsigned long long res = 0;
    for(register int i = 0; i < len; ++i)
    {
        if(s[i] >= '0' && s[i] <= '9')
        {
            res = res * 62 + s[i] - '0';                                                 
        }
        else if(s[i] >= 'A' && s[i] <= 'z')
        {
            res = res * 62 + s[i] - 'A' + 10;
        }
        else 
        {
            res = res * 62 + s[i] - 'a' + 36;
        }
    }
    return res;
}

int main()
{
    scanf("%d", &n);
    for(register int i = 1; i <= n; ++i)
    {
        scanf("%s", a[i].str);
        a[i].len = strlen(a[i].str);
        a[i].hash = Insert(a[i].str, a[i].len);
    }
    sort(a + 1, a + n + 1);
    int ans = 1;
    for(register int i = 1; i < n; ++i)
    {
        if(a[i].hash ^ a[i + 1].hash) ++ans;
    }
    printf("%d", ans);
    return 0;
}
参考程序

猜你喜欢

转载自www.cnblogs.com/kcn999/p/10290536.html