首页 > 其他分享 >洛谷题单指南-字符串-Test

洛谷题单指南-字符串-Test

时间:2024-10-16 10:03:29浏览次数:8  
标签:string int 洛谷题 字符串 longest ans Test 长度 size

原题链接:https://www.luogu.com.cn/problem/CF25E  https://codeforces.com/contest/25/problem/E

题意解读:给定a,b,c三个字符串,求包含a、b、c的最短字符串长度。

解题思路:

要得到包含a、b、c的字符串,可以通过a、b、c连接形成,而要使得连接后的字符串最短,可以尽可能的利用重叠部分

如a、b字符串连接的情况可能有三种:连续、交叉、包含

因此,对于a、b字符串连接的最短长度,可以先计算a是否包含b,如果包含b,连接后的长度即a的长度;再计算a后缀与b前缀公共长度ab,连接后长度为a.size()+b.size()-ab。

而a、b、c连接的方式一共有六种:

a->b->c

a->c->b

b->a->c

b->c->a

c->a->b

c->b->a

枚举所有情况下连接后得到的字符串长度,取最短即可。

这里有一个关键函数:int longest(string &x, string &y)

用来计算x后缀与y前缀的最长公共长度,且如果x包含y函数返回-1

STL String暴力枚举:

int longest(string &x, string &y)
{
    if(x.find(y) != string::npos) return -1; //如果x包含y
    int len = min(x.size(), y.size());
    int res = 0;
    for(int i = 1; i <= len; i++) //枚举前后缀的公共长度
    {
        string post = x.substr(x.size() - i, i); //x的后缀
        string pre = y.substr(0, i); //y的前缀
        if(post == pre) res = i; //判断是否相等
    }
    return res;
}

以上方法是O(n^2)的,必须优化

KMP优化实现:

int longest_kmp(string &x, string &y)
{
    memset(Next, 0, sizeof(Next));
    //利用y计算Next数组
    for(int i = 1, j = 0; i < y.size(); i++)
    {
        while(j && y[i] != y[j]) j = Next[j - 1];
        if(y[i] == y[j]) j++;
        Next[i] = j;
    }

    int j = 0;
    //在x中找y,如果找到返回-1,如果没找到,返回y最后匹配的位置即最大公共前后缀长度
    for(int i = 0; i < x.size(); i++)
    {
        while(j && x[i] != y[j]) j = Next[j - 1];
        if(x[i] == y[j]) j++;
        if(j == y.size()) return -1;
    }
    return j;
}

100分代码: 

#include <bits/stdc++.h>
using namespace std;

string a, b, c;
int Next[100005];

//计算相同的x的后缀和y的前缀长度,x包含y时返回-1
int longest(string &x, string &y)
{
    if(x.find(y) != string::npos) return -1; //如果x包含y
    int len = min(x.size(), y.size());
    int res = 0;
    for(int i = 1; i <= len; i++) //枚举前后缀的公共长度
    {
        string post = x.substr(x.size() - i, i); //x的后缀
        string pre = y.substr(0, i); //y的前缀
        if(post == pre) res = i; //判断是否相等
    }
    return res;
}

//用KMP优化上面的longest函数
int longest_kmp(string &x, string &y)
{
    memset(Next, 0, sizeof(Next));
    //利用y计算Next数组
    for(int i = 1, j = 0; i < y.size(); i++)
    {
        while(j && y[i] != y[j]) j = Next[j - 1];
        if(y[i] == y[j]) j++;
        Next[i] = j;
    }

    int j = 0;
    //在x中找y,如果找到返回-1,如果没找到,返回y最后匹配的位置即最大公共前后缀长度
    for(int i = 0; i < x.size(); i++)
    {
        while(j && x[i] != y[j]) j = Next[j - 1];
        if(x[i] == y[j]) j++;
        if(j == y.size()) return -1;
    }
    return j;
}

//计算x->y->z连接顺序下的最短字符串长度
long long calcu(string &x, string &y, string &z, int xy, int yz, int xz)
{
    long long res = x.size(); //加上x的长度
    if(xy >= 0) //如果y不是x的子串
    {
        res += y.size() - xy; //加上y的长度,减去y前缀和x后缀重叠部分的长度
        if(yz >= 0) res += z.size() - yz; //如果z不是y的子串,加上z的长度,减去z前缀和y后缀重叠部分的长度
    } 
    else //如果y是x的子串
    {
        if(xz >= 0) res += z.size() - xz; //如果z不是x的子串,加上z的长度,减去z前缀和x后缀重叠部分的长度
    }
    return res;
}

int main()
{
    cin >> a >> b >> c;
    int ab = longest_kmp(a, b);
    int ba = longest_kmp(b, a);
    int bc = longest_kmp(b, c);
    int cb = longest_kmp(c, b);
    int ca = longest_kmp(c, a);
    int ac = longest_kmp(a, c);

    long long ans = 1e18, t;
    //abc
    t = calcu(a, b, c, ab, bc, ac);
    ans = min(ans, t);
    //acb
    t = calcu(a, c, b, ac, cb, ab);
    ans = min(ans, t);
    //bac
    t = calcu(b, a, c, ba, ac, bc);
    ans = min(ans, t);
    //bca
    t = calcu(b, c, a, bc, ca, ba);
    ans = min(ans, t);
    //cab
    t = calcu(c, a, b ,ca, ab, cb);
    ans = min(ans, t);
    //cba
    t = calcu(c, b, a, cb, ba, ca);
    ans = min(ans, t);

    cout << ans;
    return 0;
}

 

标签:string,int,洛谷题,字符串,longest,ans,Test,长度,size
From: https://www.cnblogs.com/jcwy/p/18469081

相关文章

  • 【ICPC】The 2021 ICPC Asia Shanghai Regional Programming Contest I
    SteadilyGrowingSteam#动态规划#背包#枚举题目描述AliceenjoysplayingacardgamecalledSteadilyGrowingSteam(asknownasSGS).Inthisgame,eachplayerwillplaydifferentrolesandhavedifferentskills.Playersgetcardsfromthedeckandu......
  • 【ICPC】The 2021 ICPC Asia Shenyang Regional Contest J
    LuggageLock#搜索#枚举题目描述EileenhasabigluggageandshewouldpickalotofthingsintheluggageeverytimewhenA-SOULgoesoutforashow.However,iftherearetoomanythingsintheluggage,the4-digitpasswordlockontheluggagewill......
  • 【ICPC】The 2021 ICPC Asia Shanghai Regional Programming Contest G
    EdgeGroups#树形结构#组合数学#树形dp题目描述Givenanundirectedconnectedgraphofnnnverticesandn......
  • 【ICPC】The 2021 ICPC Asia Shanghai Regional Programming Contest H
    LifeisaGame#最小生成树#重构树#图论#贪心题目描述Agoodproblemshouldhaveaconcisestatement.Youaregivenanarrayaaaoflength......
  • Pytest参数详解 — 基于命令行模式
    Hey,大家周二好啊!今天我们来聊聊一个非常实用的话题:Pytest的命令行参数。Pytest是一个强大的Python测试框架,它支持简单的单元测试和复杂的功能测试。但是,你真的了解如何充分利用Pytest的命令行参数来优化你的测试流程吗?如果你还不是很清楚,那么这篇文章就是为你准备的!在Python的......
  • 基于FPGA的16PSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不
    1.算法仿真效果VIVADO2019.2仿真结果如下(完整代码运行后无水印): 设置SNR=30db      设置SNR=20db:     系统RTL结构图如下:   2.算法涉及理论知识概要       十六进制相位移键控(16PSK,16-PhaseShiftKeying)是一种数字调制技术,它通......
  • js数组、字符串的那些方法
    一、数组方法arr.copyWithin(a,b,c)用数组部分覆盖数组中的某些内容,改变原数组内容但长度不变a:被覆盖的起始下标;b:复制开始下标(包含);c:复制结束下标(不包含)[1,2,3,4].copyWithin(1,2,3)//[1,3,3,4]arr.flatMap(function(t,i){})拍平数组,只能拍平一层t表示第二层的每......
  • 字符串哈希
    字符串哈希哈希函数的基本性质:1)输入参数的可能性是无限的,输出的值范围相对有限2)输入同样的样本一定得到同样的输出值,也就是哈希函数没有任何随机机制3)输入不同的样本也可能得到同样的输出值,此时叫哈希碰撞4)输入大量不同的样本,得到的大量输出值,会几乎均匀的分布在整个输出域上......
  • 例2.11_2首先生成包含1000个随机字符的字符串,然后统计每个字符的出现次数,注意get()方
    #利用collections模块的Counter()函数直接作出统计 #依次加载三个模块importstring,random,collectionsx=string.ascii_letters+string.digitsy=''.join([random.choice(x)foriinrange(1000)])count=collections.Counter(y)fork,vinsorted(count.items()):......
  • python根据时间字符串获取时间,判断是否非法定节假日时间
    fromdatetimeimportdatetimefromchinese_calendarimportis_workday,is_holiday,is_in_lieu,get_holiday_detail#定义两个时间字符串time_str1="2024-10-1218:41:02"time_str2="2024-10-1217:30:00"#将时间字符串转换为datetime对象time1=datetime.......