LeetCode-字符串

本文涵盖了LeetCode中涉及字符串的各种问题,包括加粗单词、罗马数字转换、最长公共前缀、字符串查找、回文串验证、二进制求和、最长回文子串、Z字形变换、最长回文串、重复DNA序列、第一个唯一字符、子序列判断以及括号生成等。通过字典树、双指针、KMP算法等多种方法解决实际问题。
摘要由CSDN通过智能技术生成

758.字符串中加粗单词

给定一个关键词集合 words 和一个字符串 S,将所有 S 中出现的关键词加粗。所有在标签 中的字母都会加粗。
返回的字符串需要使用尽可能少的标签,当然标签应形成有效的组合。
例如,给定 words = [“ab”, “bc”] 和 S = “aabcd”,需要返回 “a<b>abc</b>d”。注意返回 “a<b>a<b>b</b>c</b>d” 会使用更多的标签,因此是错误的。
注:
words 长度的范围为 [0, 50]。
words[i] 长度的范围为 [1, 10]。
S 长度的范围为 [0, 500]。
所有 words[i] 和 S 中的字符都为小写字母。

思路
字典树
1.将words建立成一颗字典树用于查找
2.遍历字符串S,创建变量pre用于存储上一段加粗字段的最后一个位置
3.pre初始化为-1,在字符串中找到一个单词,判断这个单词是否在pre之后,若是则重新定义pre且加入"<b>"
4.细节:遍历到pre位置字符串加入"</b>",注意:最后字符串遍历完还需判断pre是否等于字符串长度!!!
5.进一步优化:pre等于字符串长度时,可直接退出(代码自行实现)

struct Node{
   
        Node* a[26];
        bool flag;
    };
    Node *root;
string boldWords(vector<string>& words, string s) {
   
        root = new Node();
        for (auto str : words) {
   
            auto p = root;
            for (int i = 0; i < str.size(); i++) {
   
                if (p->a[str[i] - 'a'] == NULL) {
   
                    p->a[str[i] - 'a'] = new Node();
                }
                p = p->a[str[i] - 'a'];
            }
            p->flag = true;
        }
        //pre表示前面是结束匹配的字符
        int pre = -1, index;
        string res = "";
        for (int i = 0; i < s.size(); i++) {
   
            auto p = root;
            index = i;
            while (s[index] && p->a[s[index] - 'a']) {
   
                p = p->a[s[index++] - 'a'];
                if (p->flag) {
   
                    if (i <= pre) {
   
                    	// i < pre说明匹配到了i之后的了
                    	//pre < index 说明pre这个结束符需要延后
                        if (pre <= index) pre = index;
                    } else {
     //如果i > pre说明已经是下一个匹配的字符了
                        res += "<b>";
                        pre = index;
                    }
                }
            }
            //表示i前面已经是需要结束符了
            if (pre == i) {
   
                res += "</b>";
            }
            res += s[i];
        }
        //pre等于末尾时需要补上
        if (s.size() == pre) {
   
            res += "</b>";
        }
        return res;
    }

13.罗马数字转整数

题目在这里插入图片描述
在这里插入图片描述

思路
罗马数字由 I,V,X,L,C,D,M 构成;
当小值在大值的左边,则减小值,如 IV=5-1=4;
当小值在大值的右边,则加小值,如 VI=5+1=6;
由上可知,右值永远为正,因此最后一位必然为正。

int romanToInt(string s) {
   
    unordered_map<char,int> map = {
   {
   'I',1} , {
   'V', 5} , {
   'X',10}, {
   'L' , 50}, {
   'C',100} , {
   'D', 500}, {
   'M', 1000}};
    int res = 0;
    int pre = map[s[0]], now;
    for (int i = 1 ; i < s.size(); i++) {
   
        now = map[s[i]];
        if (pre < now) {
   
            res -= pre;
        } else {
   
            res += pre;
        }
        pre = now;
    }
    res += pre;
    return res;
}

14.最长公共前序

题目在这里插入图片描述

思路
直接排序后第一个和最后一个进行比较

 string longestCommonPrefix(vector<string>& strs) {
   
        if(strs.empty()) return string();
        //进行排序
        sort(strs.begin(), strs.end());
        string st = strs.front(), en = strs.back();
        int i, num = min(st.size(), en.size());
        for(i =
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值