计算传入字符流中某个单词的出现次数

2024-01-17

我在面试时被问到这个问题,虽然我在 DS&Algo 方面很擅长,但我无法解决这个问题。无论如何,这是一个有趣的问题,所以发布它。

问题:您有一个传入的字符流,并且需要计算单词的出现次数。您只有一个 API 可以从流中读取数据,即stream.next_char(),如果没有,则返回“\0”。

int count_occurrences(Stream stream, String word) {
// you have only one function provided from Stream class that you can use to 
// read one char at a time, no length/size etc.
// stream.next_char() - return "\0" if end
}

输入:“aabckjhabcc” 词:“abc” 输出:2


我认为这个问题与以下想法有关 使用有限状态计算模型匹配字符串。

这个问题可以通过使用KMP字符串来解决 匹配算法。

KMP 算法尝试在模式的文本字符串中查找匹配项 字符串,通过考虑模式的前缀有多少 即使我们在某个时刻发现不匹配,仍然匹配。

用于确定“仍然可以匹配多少前缀” if 在匹配模式中的索引 i 后,我们遇到不匹配, 预先建立故障函数。 (请参考下面的代码 用于构建失效函数值)

该失效函数将告诉模式的每个索引 i, 即使这样,仍然可以匹配模式的多少前缀 我们在索引 i 之后遇到不匹配。

这个想法是找出模式的最长适当前缀的长度是多少 这也是由 1 到 i 表示的模式的每个子串的后缀 i 范围从 1 到 n 的索引。

我使用从 1 开始的字符串索引。

因此任何模式的第一个字符的失效函数值 是 0。(即到目前为止还没有匹配到任何字符)。

对于后续字符,对于每个索引 i = 2 到 n,我们看到什么 是最长的长度 模式 [1...i] 的子字符串的正确前缀,也是 模式 [1...i] 的子字符串的后缀。

假设我们的模式是“aac”,那么失败函数值为 索引1为0(尚未匹配),失败函数值 对于索引 2 为 1,(最长专有前缀的长度与 “aa”的最长正确后缀是 1)

对于模式“ababac”,索引 1 的失效函数值为 0, 索引 2 为 0,索引 3 为 1(因为第三个索引 'a' 与 第一个索引“a”),索引 4 为 2(因为索引 1 和 2 处的“ab”相同 作为索引 3 和 4 处的“ab”),索引 5 为 3(索引 [1...3] 处的“aba” 与索引 [3...5] 处的“aba”相同)。对于索引 6,失效函数值为 0。

这是构建失效函数和匹配的代码(C++) 使用它的文本(或流):

/* Assuming that string indices start from 1 for both pattern and text. */
/* Firstly build the failure function. */
int s = 1;
int t = 0;  

/* n denotes the length of the pattern */
int *f = new int[n+1];
f[1] = 0;   

for (s = 1; s < n; s++) {
    while (t > 0 && pattern[t + 1] != pattern[s + 1]) {
        t = f[t];
    }
    if (pattern[t + 1] == pattern[s + 1]) {
        t++;
        f[s + 1] = t;
    }
    else {
        f[s + 1] = 0;           
    }
}

/* Now start reading characters from the stream */
int count = 0;
char current_char = stream.next_char();

/* s denotes the index of pattern upto which we have found match in text */
/* initially its 0 i.e. no character has been matched yet. */
s = 0; 
while (current_char != '\0') {

    /* IF previously, we had matched upto a certain number of
       characters, and then failed, we return s to the point
       which is the longest prefix that still might be matched.

       (spaces between string are just for clarity)
       For e.g., if pattern is              "a  b  a  b  a  a" 
       & its failure returning index is     "0  0  1  2  3  1"

       and we encounter 
       the text like :      "x  y  z  a  b  a  b  a  b  a  a" 
              indices :      1  2  3  4  5  6  7  8  9  10 11

       after matching the substring "a  b  a  b  a", starting at
       index 4 of text, we are successful upto index 8  but we fail
       at index 9, the next character at index 9 of text is 'b'
       but in our pattern which should have been 'a'.Thus, the index
       in pattern which has been matched till now is 5 ( a  b  a  b  a)
                                                         1  2  3  4  5
       Now, we see that the failure returning index at index 5 of 
       pattern is 3, which means that the text is still matched upto
       index 3 of pattern (a  b  a), not from the initial starting 
       index 4 of text, but starting from index 6 of text.

       Thus we continue searching assuming that our next starting index
       in text is 6, eventually finding the match starting from index 6
       upto index 11.    

       */
        while (s > 0 && current_char != pattern[s + 1]) {
            s = f[s];
        }
        if (current_char == pattern[s + 1]) s++; /* We test the next character after the currently
                                                    matched portion of pattern with the current 
                                                    character of text , if it matches, we increase
                                                    the size of our matched portion by 1*/
        if (s == n) {
            count++;
        }
        current_char = stream.next_char();
}

printf("Count is %d\n", count);

`

注意:即使在重叠的模式出现中,此方法也有助于找出计数。例如,单词“aba”出现两次 在“ababa”流中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

计算传入字符流中某个单词的出现次数 的相关文章

  • 线段树java实现[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 你知道 二进制 的良好实现吗线段树 http en wikipedia org wiki Segmen
  • 简单的排名算法

    我需要创建一个民意调查 按照项目的好坏顺序创建一个排名列表 我打算向每个用户展示两个项目 让他们选择一个他们认为更好的项目 然后多次重复这个过程 它有点类似于您在社交网络电影 我应该如何根据收到的答案对项目进行排名 看着那 这ELO国际象棋
  • 自动跟踪算法

    我正在尝试写一个simple跟踪例程来跟踪电影中的某些点 本质上我有一系列 100 帧长的电影 在黑暗背景上显示一些亮点 我每帧有大约 100 150 个点 它们在电影的过程中移动 我想跟踪它们 所以我正在寻找一些有效的 但可能不会过度实施
  • Python Pandas:沿一列比较两个数据帧,并返回另一个数据帧中两个数据帧的行内容

    我正在处理两个 csv 文件并作为数据框 df1 和 df2 导入 df1 有 50000 行 df2 有 150000 行 我想将 df2 的 时间 与 df1 求时间差并返回所有列的值 对应相似的行 保存在df3中 时间同步 例如 35
  • 如何为多边形创建内部螺旋?

    对于任何形状 我如何在其内部创建类似形状的螺旋 这与边界 使用 Minkowski 和 类似 尽管它会是相同形状的螺旋 而不是在形状内部创建相同的形状 我找到了这个 http www cis upenn edu cis110 13su le
  • Python 旅行商贪婪算法 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 因此 我为旅行推销员问题创建了一种排序 并按 x 坐标和 y 坐标进行排序 我正在尝试实施贪婪搜索 但无法做到 此外 每
  • Java 2d 游戏中的路径查找?

    本质上它是我正在开发的一款吃豆人克隆游戏 我有一个 Enemy 类 并创建了该类的 4 个实例 它们都代表游戏的 4 个幽灵 所有幽灵都会在屏幕的随机区域启动 然后它们必须朝着吃豆人角色前进 当玩家控制吃豆人并移动它时 他们应该跟随它并尽可
  • 我应该对算法使用递归还是记忆化?

    如果我可以选择使用递归或记忆来解决问题 我应该使用哪一个 换句话说 如果它们都是可行的解决方案 因为它们提供了正确的输出并且可以在我正在使用的代码中合理地表达 那么我什么时候会使用其中一个而不是另一个 它们并不相互排斥 您可以同时使用它们
  • 贝尔曼福特算法可以有任意的边顺序吗?

    我刚刚开始学习新算法 但当我阅读 极客为极客而写的贝尔曼福特算法 时 我陷入了困境 http www geeksforgeeks org dynamic programming set 23 bellman ford algorithm h
  • 在一个区域中拟合二维多边形的算法?

    这有标准吗 算法名称 说 我有 10 个不同大小的多边形 我有一个特定大小的区域 我想知道如何填充该区域中的最多多边形 以及它们是如何拟合的 笔记 多边形可以根据限制集进行旋转 一个可能的名称是包装问题 http en wikipedia
  • 用于查找最近邻居的空间划分算法如何工作?

    为了找到最近的邻居 空间分区 http en wikipedia org wiki Nearest neighbor search Space partitioning是算法之一 它是如何工作的 假设我有一组 2D 点 x 和 y 坐标 并
  • 对 Java 中 *any* 类的所有实例进行全排序

    我不确定以下代码是否能确保 Comparator 的 Javadoc 中给出的所有条件 class TotalOrder
  • 在 Python 中从 Excel 复制 YEARFRAC() 函数

    因此 我使用 python 来自动执行一些必须在 Excel 中执行的重复任务 我需要做的计算之一需要使用yearfrac 这在Python中被复制了吗 I found this https lists oasis open org arc
  • 实时战略战争游戏人工智能算法

    我正在设计一款实时策略战争游戏 其中 AI 将负责控制大型六边形地图上的大量单位 可能超过 1000 个 一个单位有许多行动点 可以用于移动 攻击敌方单位或各种特殊行动 例如建造新单位 例如 一辆拥有 5 个行动点的坦克可以花费 3 个行动
  • 寻找公共子集的算法

    I have N number of sets Si of Numbers each of a different size Let m1 m2 mn be the sizes of respective sets mi Si and M
  • 使用递归返回嵌套列表中第二小的数字

    我必须归还第二小的使用递归的 python 列表中的数字 以及no loops 我所做的是创建一个辅助函数 它返回列表中 最小 第二小的 值的元组 然后我只取tuple 1 in my second smallest func def s
  • 最小化代表性整数的误差之和

    Given n integers between 0 10000 as D1 D2 Dn where there may be duplicates and n can be huge I want to find k distinct r
  • 如何实现n个元素的查找和插入操作的动态二分查找

    这个想法是使用多个数组 每个长度为 2 k 根据 n 的二进制表示来存储 n 个元素 每个数组都是排序的 不同的数组没有以任何方式排序 在上述数据结构中 SEARCH是通过对每个数组进行一系列二分查找来进行的 INSERT 是通过一系列相同
  • 找到一个数字所属的一组范围

    我有一个 200k 行的数字范围列表 例如开始位置 停止位置 该列表包括除了非重叠的重叠之外的所有类型的重叠 列表看起来像这样 3 5 10 30 15 25 5 15 25 35 我需要找到给定数字所属的范围 并对 100k 个数字重复该
  • 确定一组日期的事件重复模式

    我正在寻找一种模式 算法或库 它将采用一组日期并在退出时返回重复的描述 即集合 11 01 2010 11 08 2010 11 15 2010 11 22 2010 11 29 2010 会产生类似 十一月的每个星期一 的结果 有没有人以

随机推荐