首页 > 其他分享 >P1688 新单词接龙问题 题解

P1688 新单词接龙问题 题解

时间:2022-11-09 15:03:57浏览次数:79  
标签:tmp Hash P1688 题解 ll 枚举 接龙 字符串 长度

大家好,我喜欢 Hash,所以我用 Hash 通过了这道题


思路:

处理方法有点类似于P6521

首先我们最终接出的字符串要求其中的小字符串按字典序排序,那么我们就将所有字符串排好序后从前往后枚举(其实题目已经给我们排好序了,但有些人可能没有注意到),每次枚举到一个字符串就更新把它作为答案串结尾的最大长度。

然后注意到一一枚举从 az 的每一个字母会让复杂度爆掉,那么我们就用一个空字符(比如 #)来代替要变换的部分。

举个例子,对于字符串 adcb,它可以由 adb 加一个字符 c 变换过来,那么我们就会在枚举到 adb 时将状态 ad#b 压入到 Hash 中,之后枚举到 adcb 时就可以用 ad#b 来更新答案。

具体过程:

令当前枚举到第 \(i\) 个字符串,我们先更新这个字符串作为结尾的答案。
分三种变换(两种情况):

  1. 添加 & 修改一个字母
    枚举每一位字符,将其变为 # 后把在 Hash 中查找该串,更新找到的最大长度。
  2. 删除一个字母(当前字符串长度不能为16)
    枚举每一个字符间的位置,把 # 插进去后在 Hash 中查找,更新找到的最大长度。

将找到的最大长度 +1 后更新到最终答案里。
然后再插入这个字符串,也分三种变换两种情况,但删除和添加操作调换了一下:

  1. 删除 & 修改一个字母
    枚举每一位字符,将其变为 # 后把它塞进 Hash。
  2. 添加一个字母(当前字符串长度不能为16)
    枚举每一个字符间的位置,把 # 插进去后把串塞进 Hash。

最后我们会发现这样会让相同的字符串重复统计,那么我们在一开始就把相同的字符串去掉就好,不影响最终结果。

更具体一点看代码(写的有点 Naive):

code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline ll Max(ll x, ll y){return x > y ? x : y;}
inline ll rd(){
	ll x = 0;bool f = true;char c = getchar();
	while (c < '0' || c > '9'){if (c == '-') f = false; c = getchar();}
	while (c >= '0' && c <= '9'){x = (x<<3) + (x<<1) + (c ^ 48);c = getchar();}
    return f ? x : -x;
}
const int N = 2.5e4 + 10, M = 1e5 + 7;

class Hash_table{
    private: 

    struct Node{
        int nextt, num;// num 是 “str” 这个状态的最大长度
        string str;
    }data[N * 50];int head[M + 10], cnt;

    int h(string s){
        int l = s.size(), res = 0;
        for(int i = 0; i < l; ++i)
            res = ((res << 4) + int(s[i] - 'a') + M) % M;
        return res;
    }

    public: 

    int find(string s){
        int key = h(s);
        for(int i = head[key]; i; i = data[i].nextt)
            if(s == data[i].str)
                return data[i].num;
        return 0;
    }

    void insert(string s, int val){
        int key = h(s);
        for(int i = head[key]; i; i = data[i].nextt){
            if(s == data[i].str){
                data[i].num = Max(data[i].num, val);
                return ;
            }
        }
        data[++cnt].nextt = head[key];
        data[cnt].num = val;
        data[cnt].str = s;
        head[key] = cnt;
        return ;
    }
}H;

int n;
int ans;
string s, lst = "", tmp, tmp1, tmp2;// lst用来去重,一坨tmp用来枚举带’#’的字符串

int main(){
    n = rd();
    for(int i = 1; i <= n; ++i){
        cin >> s;
        if(s == lst)continue;
        lst = s;
        int l = s.size(), val = 0;// val是以当前串结尾的串的最大长度
		tmp = s;
        for(int j = 0; j < l; ++j){// 查找之前 添加和修改 的字符串
            tmp[j] = '#';
            val = Max(val, H.find(tmp));
			tmp[j] = s[j];
        }
        if(l < 16)// 查找之前 删除 的字符串
            for(int j = 0; j <= l; ++j){
                tmp = "", tmp1 = "", tmp2 = "";
                for(int k = 1; k <= j; ++k)// 用一堆 += 时间更优
                    tmp1 += s[k - 1];
                for(int k = j + 1; k <= l; ++k)
                    tmp2 += s[k - 1];
                tmp += tmp1;
                tmp += '#';
                tmp += tmp2;
                val = Max(val, H.find(tmp));
            }

        val++;
        ans = Max(ans, val);// 更新最终答案

		tmp = s;
        for(int j = 0; j < l; ++j){// 插入 删除和修改 后的字符串
            tmp[j] = '#';
            H.insert(tmp, val);
			tmp[j] = s[j];
        }

        if(l < 16)// 插入 添加 后的字符串
            ans = Max(ans, val);
            for(int j = 0; j <= l; ++j){
                tmp = "", tmp1 = "", tmp2 = "";
                for(int k = 1; k <= j; ++k)
                    tmp1 += s[k - 1];
                for(int k = j + 1; k <= l; ++k)
                    tmp2 += s[k - 1];
                tmp += tmp1;
                tmp += '#';
                tmp += tmp2;
                H.insert(tmp, val);
            }
    }
    printf("%d", ans);
	return 0;
}

标签:tmp,Hash,P1688,题解,ll,枚举,接龙,字符串,长度
From: https://www.cnblogs.com/cotsheep/p/16873675.html

相关文章

  • 问题解决-白鹭引擎Egret Wing3修改项目内容后进行调试,项目仍显示修改前样式
    问题描述:修改前: 修改后: 解决方法:点击上方菜单栏项目-清理,进行项目清理    点击菜单栏项目-调试  重新进行调试。  调试成功后,问题成功解......
  • 问题解决-白鹭引擎Egret Wing3调试出错,输出台显示乱码而且编译终止问题Failed to load
    问题描述:Failedtoloadresource:theserverrespondedwithastatusof404()未能加载资源:服务器响应,状态为404() 解决方法:卸载引擎并重新安装,安装时使用默认路径(C......
  • maven打包失败,Could not resolve dependencies for project...Could not find artifac
    一、问题原因:在阿里私服或者Maven的中央仓库找不到Pom文件引入的Jar,也就是说,你想引的依赖Jar包根本没有成功加载到项目中。二、分析2.1这个包可能处于隐患或者其他原因,原作......
  • CF1750题解
    A.IndirectSort首先,如果\(a_i>a_k\),\(a_i\)就会变大,而这样的操作是没有意义的.因此操作可以转换为\(\forallj,k(j<k)\),如果\(\existsi,i<j\),使得\(a[i]<=a[k]\),......
  • [CSP-S 2022]数据传输 题解
    提示:我这个方法比其它解法还要麻烦,目前最简洁的解法是dottle的解法,推荐阅读,我仅在此说明我的思路。给定\(n\)个点的树,点\(i\)的点权为\(a_i\),给定整数\(k\)。称......
  • 线上问题解决
    1.服务重启2.部署回滚3.限流降级利用日志和故障现场保留的dump文件等进行根因分析;修复故障后在测试环境进行验证,确认没问题后再发布到生产环境;记录故障从发生到彻底......
  • cannot resolve symbol 'String' 问题解决
    在拉取一个新的项目的时候,maven和jdk都是配置好的,没问题,但是String会报红,显示cannotresolvesymbol'String'。maven的setting文件需要更改内容,因公司有自己的特殊的依......
  • CS Academy Telegraph 题解 (分层DP)
    CSAcademy是一个比较小众的罗马尼亚OJ,UI好看功能多样,但是需要fq才能注册。访问是不用fq的常用工具:画图找不同题目链接前段时间刚做过类似的分层dp题,这次又忘了,深刻反......
  • 题解 ABC154F【Many Many Paths】
    problem令\(f(i,j)\)表示,在平面直角坐标系中,从\((0,0)\)出发,每次向上或向右走一步,到达\((i,j)\)的方案数,求:\[\sum_{l_1\leqi\leqr_1}\sum_{l_2\leqj\leqr_2}f(......
  • CSP-S 2022 题解
    A假期计划若\(u\)转车不超过\(k\)次可以到达\(v\),相当于\(u\leadstov\)的最短路长度不超过\(k+1\)。对于每个点\(u\),我们首先预处理满足如下条件的点\(v\)......