IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> leetcode 1316. 不同的循环子字符串—(每日一难day18) -> 正文阅读

[数据结构与算法]leetcode 1316. 不同的循环子字符串—(每日一难day18)

1316. 不同的循环子字符串

给你一个字符串 text ,请你返回满足下述条件的 不同 非空子字符串的数目:

可以写成某个字符串与其自身相连接的形式(即,可以写为 a + a,其中 a 是某个字符串)。
例如,abcabc 就是 abc 和它自身连接形成的。

示例 1:

输入:text = “abcabcabc”
输出:3
解释:3 个子字符串分别为 “abcabc”,“bcabca” 和 “cabcab”。

示例 2:

输入:text = “leetcodeleetcode”
输出:2
解释:2 个子字符串为 “ee” 和 “leetcodeleetcode” 。

提示:

1 <= text.length <= 2000
text 只包含小写英文字母。

解析

  • 题目要求不同的循环字符串长度,因此可以枚举长度[2,n/2]。
  • 需要用到set去重,但是将字符串加入set的复杂度为O(N),子串比较的复杂度也是O(N),因此需要用到字符串hash的技巧。
  • 字符串hash,简单来讲就像要将字符串"123"转换为数字123一样,数字的每次进制为10,字符串的可以取26 (一般取大于26的质数,防止冲突)。
  • 我们用pre[i]表示字符串[0:i]表示的hash,那么就可以根据pre将s[i:j]的hash表示出来。怎么表示呢?下边举个例子。

假如:字符串 s=“123”

  1. pre[0]=0
  2. pre[1]=pre[i-1]*10+s[0]-‘0’=1;
  3. pre[2]=pre[i-1]*10+s[1]-‘0’=12;
  4. pre[3]=pre[i-1]*10+s[2]-‘0’=123;

如果想获取子串 “23” 对应的值
对应字符串的下标分别为l=1,r=2
只需要用pre[3]-pre[1]*100=123-1*100=23(也就是pre[r+1]-pre[l]*base[r-l+1])
这里的100由字符串的长度决定,可以用一个mul数组存放不同长度的字符串要乘的底数

  1. mul[0]=1
  2. mul[1]=10
  3. mul[2]=100
  4. mul[3]=1000

到这里我们就能将字符串转换为数字了,但是可以发现字符串如果过长的话正常会溢出,因此需要取余操作。

pre[i] = ((ll)pre[i - 1] * base + text[i - 1]) % mod;
mul[i] = (ll)mul[i - 1] * base % mod;

在通过hash = pre[r+1] - pre[l] * base[r-l+1] 获取hash值时,
有可能会使pre[l] * base[r-l+1]溢出,
因此,hash = pre[r+1] - pre[l] * base[r-l+1]%mod.

由于已经对pre数组元素取余操作,
因此 pre[r+1] - pre[l] * base[r-l+1]%mod* 可能为负数.
例如11%10=1,5%10=5,1-5<0。
所以,hash=( pre[r+1] - pre[l] * base[r-l+1]%mod + mod)*。

到这里就完整的得到了子串对应的hash值.

相同技巧题目

 int gethash(int l,int r,vector<int>& pre,vector<int>& mul){
        return (pre[r + 1] - (ll)pre[l] * mul[r - l + 1] % mod + mod) % mod;
    }

code

typedef long long ll;
class Solution {
    constexpr static int mod = (int)1e9 + 7;
public:
    // 枚举每个长度,然后滑动窗口
    int base=31;
    int res=0;
    int gethash(int l,int r,vector<int>& pre,vector<int>& mul){
        return (pre[r + 1] - (ll)pre[l] * mul[r - l + 1] % mod + mod) % mod;
    }
    void check(string s,int k,vector<int>& pre,vector<int>& mul){
        int n=s.size();
        unordered_set<int> se;
        for(int i=0;i<n-2*k+1;i++){
            int fir=gethash(i,i+k-1,pre,mul);
            int lst=gethash(i+k,i+2*k-1,pre,mul);
            if(fir==lst&&se.find(fir)==se.end()){
                se.insert(fir);
                res++;
            } 
        }
    }

    int distinctEchoSubstrings(string text) {
        int n=text.size();
        if(n==1)
            return 0;
        int base = 31;
        vector<int> pre(n + 1), mul(n + 1);
        pre[0] = 0;
        mul[0] = 1;
        // 用pre[i]表示text[0:i]的hash值,不包括text[i]
        for (int i = 1; i <= n; ++i) {
            pre[i] = ((ll)pre[i - 1] * base + text[i - 1]) % mod;
            mul[i] = (ll)mul[i - 1] * base % mod;
        }

        for(int i=1;i<=n/2;i++){
            check(text,i,pre,mul);
        }
        return res;
    }
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-14 10:09:04  更:2022-05-14 10:09:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:36:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码