字符串c++练习(KMP等)

news2025/7/6 17:19:03

反转字符串

文章目录

    • 反转字符串
    • 反转字符串||
    • 替换空格
    • 翻转字符串里的单词
    • 左旋转字符串
    • 找出字符串中第一个匹配项的下标
  • 【模板】KMP字符串匹配
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 样例 1 解释
      • 数据规模与约定
    • 重复的字符串
  • [BOI2009]Radio Transmission 无线传输
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
        • 样例输入输出 1 解释
        • 规模与约定

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
class Solution {
public:
    void reverseString(vector<char>& s) {
    //    int i=0;
    //    int j=s.size()-1;
    //    while(i<j){
    //        swap(s[i],s[j]);
    //        i++;
    //        j--;
    //    }
    reverse(s.begin(),s.end());
    }
};

反转字符串||

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:

输入:s = "abcdefg", k = 2
输出:"bacdfeg"
class Solution {
public:
    string reverseStr(string s, int k) {
    //     for(int i = 0; i<s.size();i+=(2*k)) {
    //         //每隔2k个字符后前的前k个字符进行反转
    //         //剩余字符小于2k但大于等于k个,反转前k个字符
    //         if(i+k<=s.size()) {
    //             //反转i到i+k个字符
    //             reverse(s.begin()+i,s.begin()+i+k);
    //         } else {
    //             reverse(s.begin()+i,s.end());
    //         }
    //     }
    //     return s;
    // }
    int n = s.length();
    for(int i = 0;i<n;i+=2*k) {
        reverse(s.begin()+i,s.begin()+min(i+k,n));
    }
    return s;
    }
};

替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy."
class Solution {
public:
    string replaceSpace(string s) {
        // int count = 0 ;
        // int OldSize = s.size();
        // for (int i = 0; i< s.size();i++) {
        //     if(s[i]==' ') {
        //         count++;
        //     }
        // }
        // //扩充字符串s的大小,也就是每个空格替换成“%20”之后的大小
        // s.resize(s.size()+count*2);
        // int NewSize = s.size();
        // //从后先前将空格替换为"%20" 
        // int j = OldSize-1;
        // int i = NewSize-1;
        // while(j<i) {
        //     if(s[j]!=' ') {
        //         s[i]=s[j];
        //     } else {
        //         s[i]='0';
        //         s[i-1]='2';
        //         s[i-2]='%';
        //         i-=2;
        //     }
        //     i--;
        //     j--;
        // }
        // return s;
        string array;
        for(auto &c : s){
            if(c==' '){
                array.push_back('%');
                array.push_back('2');
                array.push_back('0');
            }
            else {
                array.push_back(c);
            }
        }
        return array;
    }
};

翻转字符串里的单词

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:
输入: "the sky is blue"
输出: "blue is sky the"

示例 2:
输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:
输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
class Solution {
public:
    string reverseWords(string s) {
    //     //O(n)
    // reverse(s.begin(),s.end());
    // int n = s.size();
    // int idx = 0;
    // for ( int start = 0;start < n;start++) {
    //     if(s[start]!=' '){
    //         // 填一个空白字符然后将idx移动到下一个单词的开头位置
    //         if(idx != 0) {
    //             s[idx++]=' ';
    //         }
    //         // 循环遍历至单词的末尾
    //         int end = start;
    //         while(end<n&&s[end]!=' ')
    //         s[idx++]=s[end++];
            
    //             // 反转整个单词
    //         reverse(s.begin()+idx-(end-start),s.begin()+idx);
            
    //             // 更新start,去找下一个单词                         
    //         start = end;
    //     }
    // }
    // //删除
    // s.erase(s.begin()+idx,s.end());
    // return s;
    
    //双端队列
    //O(n)
    int left = 0,right = s.size()-1;
    //去掉开头的空白字符
    while(left<=right && s[left]==' ')
    ++left;
    //去掉结尾的空白字符
    while(left<=right && s[right]==' ')
    --right;
    //队列
    deque<string> d;
    string word;
    while(left<=right) {
        char c = s[left];
        //添加单词到队列里
        if(word.size() && c==' ') {
            d.push_front(move(word));
            word="";
        }
        //一个一个字母添加
        else if(c!=' ') {
            word+=c;
        }
        ++left;
    }
    //添加最后一个单词
    d.push_front(move(word));
    string ans;
    //判断单词,拿一个单词添加一个空格
    while(!d.empty()) {
        ans+=d.front();
        d.pop_front();
        if(!d.empty())
        ans+=' ';
    }
    return ans;

    }
};

左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:
输入: s = "abcdefg", k = 2
输出: "cdefgab"

示例 2:
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(),s.begin()+n);
        reverse(s.begin()+n,s.end());
        reverse(s.begin(),s.end());
        return s;
    }
};

找出字符串中第一个匹配项的下标

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 。

示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
class Solution {
public:
    // void getNext(int* next, const string& s){
    //    int j = -1;
    //    next[0]=j;
    //     for(int i = 1; i<s.size();i++) { //i从1开始
    //         while(j>=0&&s[i]!=s[j+1]) { //前后缀不相同
    //             j=next[j];  //向前后退
    //           }
    //         if(s[i]==s[j+1]) {  //找到相同的前后缀
    //             j++;
    //         }
    //         next[i] = j;    //将j赋值给next[i]
          
    //     }
    // }
    // int strStr(string haystack, string needle) {
    //     if(needle.size()==0)
    //     return 0;
    //     int next[needle.size()];
    //     getNext(next,needle); 
    //     int j = -1; //因为next数组记录的起始位置为-1
    //     for ( int i = 0; i < haystack.size() ; i++) {
    //         while (j >=0 && haystack[i] != needle[j+1]) { //不匹配
    //             j = next[j]; //寻找之前匹配的位置
    //         }
    //         if(haystack[i]==needle[j+1]){//匹配成功
    //             j++;
    //         } 
    //         if (j == (needle.size() - 1)) { //文本串s里出现了模式串t
    //             return (i-needle.size() +1);
    //         }
    //     }
    //     return -1;
    // }

    int strStr(string s, string p) {
        int n = s.size(),m = p.size();
        if(m ==0) 
        return 0;
        //设置哨兵
        s.insert(s.begin(),' '); //文本串
        p.insert(p.begin(),' '); //模式串
        vector<int> next(m+1);
        //预处理
        for ( int i =2,j = 0;i<=m;i++) {
            while(j&&p[i]!=p[j+1]) //不匹配
            j=next[j];
            if(p[i]==p[j+1])//匹配
            j++;
            next[i] = j;//将j赋值给next[i]
        }
        //匹配过程
        for(int i=1,sj=0;i<=n;i++) {
            while(j&&s[i]!=p[j+1])
            j=next[j]; //退后
            if(p[j+1]==s[i])
            j++; 
            if(j==m )
            return i-m; 

        }
        return -1;
    }

};

【模板】KMP字符串匹配

题目描述

给出两个字符串 $s_1$$s_2$,若 $s_1$ 的区间 $[l, r]$ 子串与 $s_2$ 完全相同,则称 $s_2$$s_1$ 中出现了,其出现位置为 $l$
现在请你求出 $s_2$$s_1$ 中所有出现的位置。

定义一个字符串 $s$ 的 border 为 $s$ 的一个$s$ 本身的子串 $t$,满足 $t$ 既是 $s$ 的前缀,又是 $s$ 的后缀。
对于 $s_2$,你还需要求出对于其每个前缀 $s'$ 的最长 border $t'$ 的长度。

输入格式

第一行为一个字符串,即为 $s_1$
第二行为一个字符串,即为 $s_2$

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 $s_2$$s_1$ 中出现的位置。
最后一行输出 $|s_2|$ 个整数,第 $i$ 个整数表示 $s_2$ 的长度为 $i$ 的前缀的最长 border 长度。

样例 #1

样例输入 #1

ABABABC
ABA

样例输出 #1

1
3
0 0 1

提示

样例 1 解释

对于 $s_2$ 长度为 $3$ 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 $1$

数据规模与约定

本题采用多测试点捆绑测试,共有 3 个子任务

  • Subtask 1(30 points):$|s_1| \leq 15$$|s_2| \leq 5$
  • Subtask 2(40 points):$|s_1| \leq 10^4$$|s_2| \leq 10^2$
  • Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 $1 \leq |s_1|,|s_2| \leq 10^6$$s_1, s_2$ 中均只含大写英文字母。

#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
int kmp[MAXN];
int la,lb,j=0;
char a[MAXN],b[MAXN];
int main() {
    //往后移一位输入1开始,这样就不需要从-1开始
    cin>>a+1;
    cin>>b+1;
    la=strlen(a+1);
    lb=strlen(b+1);
    for (int i=2;i<=lb;i++)
    {   
        //匹配不成功
        while(j&&b[i]!=b[j+1]) {
            j=kmp[j]; //退后
        }
        //匹配成功
        if(b[i]==b[j+1])
        j++;
        //赋值
        kmp[i]=j;
    }
    j=0;
    for(int i=1;i<=la;i++) {
        while(j>0&&b[j+1]!=a[i])
        j=kmp[j];
        if(b[j+1]==a[i])
        j++;
        if(j==lb)
        {
            cout<<i-lb+1<<endl;
            j=kmp[j];
        }
    }
    for(int i=1;i<=lb;i++) 
    cout<<kmp[i]<<" ";
    return 0;
    
}

重复的字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。



示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。
class Solution {
public:
    // bool repeatedSubstringPattern(string s) {
    //     int n = s.size();
    //     for (int i = 1;i*2<=n;++i) {
    //         if (n%i == 0) {
    //             bool match = true;
    //             for(int j=i;j<n;++j) {
    //                 if(s[j]!=s[j-i])
    //                 {
    //                     match = false;
    //                     break;
    //                 }
    //             }
    //             if(match) {
    //                 return true;
    //             }
    //         }
    //     }
    //     return false;
    // }
    void getNext (int * next, const string& s) {
        next[0] = -1;
        int j = -1;
        for(int i = 1;i<s.size();i++) {
            while(j>=0&&s[i]!=s[j+1]) {
                j=next[j];
            }
            if(s[i] == s[j+1]) {
                j++;
            }
            next[i]=j;
        }
    }
    bool repeatedSubstringPattern (string s) {
        if(s.size()==0) {
            return false;
        }
        int next[s.size()];
        getNext(next,s);
        int len = s.size();
        //(len - (next[len - 1] + 1)) 也就是: 12(字符串的长度) - 8(最长公共前后缀的长度) = 4, 4正好可以被 12(字符串的长度) 整除,所以说明有重复的子字符串(asdf)
        if(next[len-1]!=-1&&len%(len-(next[len-1]+1))==0) {
            return true;
        }
        return false;
    }
};

[BOI2009]Radio Transmission 无线传输

题目描述

给你一个字符串 s 1 s_1 s1,它是由某个字符串 s 2 s_2 s2 不断自我连接形成的。但是字符串 s 2 s_2 s2 是不确定的,现在只想知道它的最短长度是多少。

输入格式

第一行一个整数 L L L,表示给出字符串的长度。

第二行给出字符串 s 1 s_1 s1 的一个子串,全由小写字母组成。

输出格式

仅一行,表示 s 2 s_2 s2 的最短长度。

样例 #1

样例输入 #1

8
cabcabca

样例输出 #1

3

提示

样例输入输出 1 解释

对于样例,我们可以利用 abc \texttt{abc} abc 不断自我连接得到 abcabcabc \texttt{abcabcabc} abcabcabc,读入的 cabcabca \texttt{cabcabca} cabcabca,是它的子串。

规模与约定

对于全部的测试点,保证 1 < L ≤ 1 0 6 1 < L \le 10^6 1<L106

#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000010
int kmp[MAXN];
int j;
int L;
char a[MAXN];
int main() {
    cin>>L;
    cin>>a+1;
    for(int i=2;i<=L;i++) {
        while(j>0&&a[i]!=a[j+1])
        j=kmp[j];
        if(a[i]==a[j+1])
        j++;
        kmp[i]=j;
    }
    cout<<L-kmp[L]<<endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】Linux中的环境变量及其意义

目录 一、环境变量的概念 1、让自己写的可执行程序无需路径即可执行的方法 1.1将可执行程序拷贝至/usr/bin/目录下 1.2将test的绝对路径添加至PATH中 二、环境变量相关的命令 三、getenv()&#xff08;获取环境变量&#xff09; 四、main函数命令行参数的解析及意义 1、…

如何基于TS在React中使用Redux Toolkit

什么是Redux Redux 是 JavaScript 应用程序的状态容器&#xff0c;提供可预测的状态管理.可以帮助你开发出行为稳定可预测的、运行于不同的环境&#xff08;客户端、服务器、原生应用&#xff09;、易于测试的应用程序。不仅于此&#xff0c;它还提供超爽的开发体验&#xff0…

【Pytorch with fastai】第 3 章 :数据伦理

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

CentOS7安装MySQL(亲测版)

1 Yum Repository下载安装包文件 [rootlocalhost home]# wget https://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm2 使用yum安装mysql yum install mysql-server执行后报错&#xff0c;官方5.7版本默认没有GPG key, 需要在上述命令上 添加 --nogpgcheck …

图解计算机内部的高速公路 —— 总线系统

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 在之前的文章中&#xff0c;我们聊到了计算机的冯诺依曼计算…

2022-09-17青少年软件编程(C语言)等级考试试卷(五级)解析

​​​​​​T1. 城堡问题 【题目描述】 图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成mn(m≤50,n≤50)个方块,每个方块可以有0~4面墙。 【输入】 程序从标准输入设备读入数据。第1、2行每行1个整数,分别是南北向、东西…

MySQL数据库基础

文章目录一. 数据库的操作二. 数据库中常用的数据类型三.表的操作四. 总结一. 数据库的操作 1. 创建数据库 创建语法1 crate database [这里填入表名称]; 说明&#xff1a;当我们创建数据库没有指定字符集和校验规则时&#xff0c;系统使用默认字符集&#xff1a;utf8&#xf…

(十二)Jmeter测试dubbo接口

一、概览 先去https://github.com/thubbo/jmeter-plugins-for-apache-dubbo下载扩展jar包将下载的jar包复制到 jmeter/lib/ext/下重启Jmeter创建Dubbo取样器 二、实操 添加dubbo取样器 输入请求详情 参数类型可以在 https://github.com/thubbo/jmeter-plugins-for-apache-…

如何在Retail Link网站上与Walmart进行EDI连接测试?

本文主要介绍通过沃尔玛Walmart供应商平台Retail Link与沃尔玛Walmart建立EDI连接的流程。沃尔玛Walmart作为零售行业中最先使用AS2协议传输EDI数据的企业之一&#xff0c;其AS2经过多年的使用检验&#xff0c;具有安全连接、灵活数据传输等优点&#xff0c;使其经久不衰&#…

Qt Xml文件的创建和解析[xml和dom方式]

Qt Xml文件的创建和解析[xml和dom方式] 【1】Qt XML使用说明【2】Qt XML未来可期【3】Qt XML文件格式【4】Qt 读取XML文档的方法【5】Qt XML解析方式比较【6】QXmlStreamReader类说明【7】QXmlStreamWriter类说明【8】DOM说明【9】XML常用函数【10】DOM常用函数【11】XML和DOM源…

摊牌了,请各位做好一年内随时失业的准备

前两天跟一个HR朋友聊天&#xff0c;她表示刚在boss上发布了一个普通测试岗位&#xff0c;不到一小时竟然收到了几百份简历。而且简历质量极高&#xff0c;这是往年不敢想象的。岗位少&#xff0c;竞争激烈&#xff0c;这是今年软件测试就业的真实写照&#xff0c;也是所有岗位…

Python开发环境及常用Web框架

Python Python是一门易于学习、功能强大的编程语言。它提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。Python 优雅的语法和动态类型以及解释型语言的本质&#xff0c;使它成为多数平台上写脚本和快速开发应用的理想语言。 吉多范罗苏姆&#xff08;Guido…

基于Postmate实现的跨域通信

1、Postmate 介绍 是一款基于 postMessage 来处理父子页面通信的库&#xff0c;轻量且好用。一个强大的、简单的、基于 promise 的 postMessage iFrame 通信库。 postmate 官方地址 https://github.com/dollarshaveclub/postmate 2、Postmate 特性 基于 promise 的 API&…

如何将数字改为千分符且保留两位小数显示?toLocaleString()和toFixed(2)踩坑

前言 基于现代Web前端框架的应用&#xff0c;其原理是通过浏览器向服务器发送网络请求&#xff0c;获取必要的index.html和打包好的JS、CSS等资源&#xff0c;在浏览器内执行JS&#xff0c;动态获取数据并渲染页面&#xff0c;从而将结果呈现给用户。在这个过程中&#xff0c;…

【java学习】 static

文章目录成员变量static 工具类static 代码块设计模式继承重写成员变量 1&#xff0e;成员变量的分类和访问分别是什么样的? 静态成员变量&#xff08;有static修饰&#xff0c;属于类、加载一次&#xff0c;可以被共享访问)&#xff0c;访问格式 类名.静态成员变量(推荐) 对…

R语言七天入门教程六:文件相关操作

R语言七天入门教程六&#xff1a;文件相关操作 一、文件的读写 R 语言作为统计学编程语言&#xff0c;常常需要处理大量数据&#xff0c;而这些数据通常会从文件中进行读取&#xff0c;因此文件读写在R语言中是非常重要的操作。在R语言中&#xff0c;用到最多的文件格式是csv…

Carla安装记录

Carla安装记录 最近打算在做一些自动驾驶相关的东西&#xff0c;所以安装了一下Carla。在这里记录一些自己的安装过程中遇到的一些问题和解决的方法。 Carla release版本下载 想要安装Carla&#xff0c;可以选择release版本或者源码安装。在这里我主要介绍release版本的安装…

Vue3、vite项目页面自适应配置(postcss-plugin-px2rem、amfe-flexible)

文章目录前言&#xff1a;vite 如何处理 csspostcss项目配置下载相关包配置方案一方案二&#xff08;备选方案&#xff09;相关资料链接前言&#xff1a;vite 如何处理 css vite 天生就支持对css文件的直接处理 关于预处理器 ☀️目前&#xff0c;在工程化开发中&#xff0c;使…

AcWing-C/C++语法基础【合集2】

5.字符串 每个常用字符都对应一个-128~127的数字 &#xff0c;二者之间可以相互转化&#xff1a; (int)97 , (char)a 常用ASCII值&#xff1a;’A’-‘Z’ 是65~90&#xff0c;’a’-‘z’是97-122&#xff0c;’0’-‘9’是 48-57 字符可以参与运算&#xff0c;运算时会将其当…

2022年11月编程排行榜

2022年11月Tiobe编程排行榜已更新&#xff0c;研一的生涯也快结束&#xff0c;来看一下本月各大编程语言有何新进展&#xff1a; 目录&#xff1a;11月编程排行榜一、榜单情况二、榜单简单的分析一、榜单情况 这里只展示排名靠前的前15名&#xff1a; TOP 10编程语言TIOBE指数…