题解 Luogu P3370

讲讲这题的几种做法:

暴力匹配法

rt,暴力匹配,即把字符串存起来一位一位判相等

时间复杂度$ O(n^2·m) $

再看看数据范围

$n\le10^5,m\le10^3$

当场爆炸。当然有暴力分

代码(20pts):

#include <bits/stdc++.h>
using namespace std;
char c[100001][1001];
bool pd(int x, int y)
{
    int l1 = strlen(c[x]), l2 = strlen(c[y]);
    if(l1 != l2) return 0;
    for(int i = 0; i < l1; i++)
    {
        if(c[x][i] != c[y][i]) return 0;
    }
    return 1;
}
int main()
{
    int n;
    cin >> n;
    int ans = n;
    for(int i = 1; i <= n; i++)
    {
        cin >> c[i];
        for(int j = 1; j < i; j++)
        {
            if(pd(i, j)) ans--;
        }
    }
    cout << ans;
    return 0;
}

好漂亮呀

不要问我为什么WA了,我也没想调

string法

比较正常的方法

思路就是把所有串存下来,用string自带的运算符(大于等于小于)进行字典序排序

然后按照字典序判断是否重复即可

时间复杂度嘛

$O(n·logn)$的,可以

代码(100pts):

#include <bits/stdc++.h>
using namespace std;
string s[10001];
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> s[i];
    }
    sort(s + 1, s + n + 1);//因为string自带大于和小于所以不用cmp
    int ans = n;
    for(int i = 1; i < n; i++)
    {
        if(s[i] == s[i + 1]) ans--;
            //若两个字符串相同则他们的字典序一定是相邻的
    }
    cout << ans;
    return 0;
}

C++STL法

我们当然可以用万能的STL做啦~

先来思考:我们判断一个数字是否重复是什么方法呢?

当然是bool used[1001] 啦

而这题要求判断的是字符串怎么办

把数组下标弄成string类型呗

请出主角:map

简单来讲,我们在定义数组时,只能确定数组中数的类型(比如char、bool、int、long long等等),而下标类型是固定的,即整数型

然而map可以确定这两个类型,也就是说,我们甚至可以把字符串作为下标,数字作为基本类型,来一个“反数组”(别问我反数组是啥,字面意思)

(那是不是要写成$a_{interesting} = 3$了)

那么结合上上上上上上上句话,这题就可做啦!

时间复杂度不明 反正能过就是了

代码(100pts):

#include <bits/stdc++.h>
using namespace std;
map < string , bool > m;//定义一个以string类型为下标的bool数组
string s;
int main()
{
    int n;
    cin >> n;
    int ans = n;
    for(int i = 1; i <= n; i++)
    {
        cin >> s;
        if(m[s]) ans--;
        else m[s] = 1;
    }
    cout << ans;
    return 0;
}

比暴力短

HASH法

不要问为什么是最后,你见过哪个游戏让你一开始就打BOSS的?

这个和C++STL法有异曲同工之妙 说反了吧

既然字符串当不了下标,我们就把字符串转成数字嘛。

具体请看那个有几百个赞的dalao的题解吧([email protected]_皎月半洒花%%%%%%~~)

代码(单hash,100pts):

#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
ull base = 131;
ull a[100001];
char c[10001];
ull hashe(char s[])
{
    int l = strlen(s);
    ull ans = 0;
    for(int i = 0; i < l; i++)
    {
        ans = (ans * base + (ull)(s[i])) % 200408020617;
    }
    return ans;
}
int main()
{
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> c;
        a[i] = hashe(c);
    }
    sort(a + 1, a + n + 1);
    ull ans = 1;
    for(int i = 1; i < n; i++)
    {
        if(a[i] != a[i + 1]) ans++;
    }
    cout << ans;
    return 0;
}

注:模数只写阳历生日太短会被卡?那就把 女朋友的 阴历生日加在后面鸭

原文地址:https://www.cnblogs.com/H2SO4/p/11616952.html

时间: 2024-10-10 15:11:42

题解 Luogu P3370的相关文章

题解 luogu P1850 【换教室】

题解 luogu P1850 [换教室] 时间:2019.8.6 一晚上(约 3.5h 写完) 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 \(2n\) 节课程安排在 \(n\) 个时间段上.在第 \(i\)(\(1 \leq i \leq n\))个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 \(c_i\) 上课,而另一节课程在教室 \(d_i\) 进行. 在不提交任何申请的情况下,学生们需要

题解 luogu P5021 【赛道修建】

题解 luogu P5021 [赛道修建] 时间:2019.8.9 20:40 时间:2019.8.12 题目描述 C 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 \(m\) 条赛道. C 城一共有 \(n\) 个路口,这些路口编号为 \(1,2,\dots,n\),有 \(n-1\) 条适合于修建赛道的双向通行的道路,每条道路连接着两个路口.其中,第 \(i\) 条道路连接的两个路口编号为 \(a_i\) 和 \(b_i\),该道路的长度为 \(l_i\).借助这 \(n-1\) 条

题解 Luogu P2499: [SDOI2012]象棋

关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可以通过改变顺序使这一次移动合法 证明: 考虑到达位置上的那个棋子, 如果它没有到达最终位置, 则我们考虑将该棋子移至下一步, 如果下一步还有没有到达最终位置的棋子, 则也移动它 否则直接调换这两个棋子的移动顺序即可 好的我们去除了题目中的要求: 「移动过程中不能出现多颗棋子同时在某一格的情况」, 接

luogu P3370 【模板】字符串哈希

题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:) 输入输出格式 输入格式: 第一行包含一个整数N,为字符串的个数. 接下来N行每行包含一个字符串,为所提供的字符串. 输出格式: 输出包含一行,包含一个整数,为不同的字符串个数. 输入输出样例 输入样例#1: 5 abc aaaa abc abcc 12345 输出样例#1: 4 说明

题解 luogu P1501【[国家集训队]Tree II】(Link-Cut-Tree)

Link-Cut-Tree 的懒标记下传正确食用方法. 我们来逐步分析每一个操作. 1:+ u v c:将u到v的路径上的点的权值都加上自然数c; 解决方法: 很显然,我们可以 split(u,v) 来提取u,v这一段区间,提取完了将 Splay(v),然后直接在v上打加法标记add即可. 代码: inline void pushadd(ll x,ll val){//打标记 s[x]+=sz[x]*val,v[x]+=val,add[x]+=val; s[x]%=MOD,v[x]%=MOD,ad

[题解] luogu P1985 [USACO07OPEN]翻转棋

题面 今天学搜索,正好水一发以前做的这道毒瘤题 话说这道题做了我一天,别人都是各种优化,不超100行 天真的我硬核刚了220行,全程0优化水过 但其实不用这么长,我有的函数写的有点重复了( 思路: 显然是dfs,一行一行的来 搜到[i, j]时(i > 1),看[i - 1, j]是否为黑,是的话就翻转[i, j], 也就是说搜完当前行就要保证上一行的棋全都翻成了白色 当搜到最后一行时, 既要保证上一行翻成白色,还要保证自己也都翻成白色, 最后还要特判一下最后两个的翻转. 当时年少轻狂,我想着层

[题解] luogu P1514 引水入城 DFS + 贪心覆盖区间

原题链 打了一上午,我真是弱爆了 看完题目,可以很显然的想到一种搜法: DFS/BFS第1个到第m个临湖城市,求出干旱区城市能否全有水,很显然,这样时间会炸 此时,我们可以在选择搜第i个临海城市加一个剪枝: if (c[1][i-1] < c[1][i] && c[1][i+1] < c[1][i]) dfs(); 意思说,当且仅当 i 的前一个临湖城市和后一个临海城市的海拔都小于当前临湖城市海拔,我才去搜这个城市 为什么? 你会发现,一个临湖城市要是比自己相邻的临湖城市海拔小

[题解]luogu P2257 YY的GCD

袁野的gcd 首先可以肯定的是这是一道数论题 所以题目就是: \(\sum_{i=1}^N \sum_{j=1}^M [gcd(i,j)\in prime]\) 接下来就可以愉快的推式子了~ 首先可以按套路枚举 prime 和 gcd \(\sum_{p \in prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)=p]\) 所以我们显然可以将\(i\)和\(j\) 同时除以 \(p\),得到 \(\sum_{p\in prime}\sum_{i=1}^{N}\sum_

题解 luogu P4415 【[COCI2006-2007#2] KOLONE】

一道纯模拟题. 将两队合并为一个字符串,用一个数组记录蚂蚁的方向,左队为0,右队为1.每一个时间点,两个两个字符地扫一遍字符串.由于0只能往右走,1只能往左走,所以只要在当前的两个字符中,第一个是0,第二个是1,就执行交换(同时交换方向数组和字符串),并且扫描指针加2.否则指针加1. 需要注意的是队伍合并时1左队顺序需要翻转. 自我感觉讲得比较明白了, 下贴代码: #include <bits/stdc++.h> using namespace std; int n1, n2, t, a[10