Форум программистов, компьютерный форум, киберфорум
JavaScript для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/21: Рейтинг темы: голосов - 21, средняя оценка - 4.62
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59

Метод поиска подстроки в строке

01.05.2019, 15:50. Показов 4328. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Это алгоритм потска подстроки в строке. Но если подстрока 24 символа и длиннее, метод перестаёт работать. В чём причина?
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
function countHash(text, pPow, r)
{
    var hs = 0;
    var textLength = text.length;
    for(var i = 0; i < textLength; i++)
    {
        hs += (pPow[textLength - 1 - i] * text[i].charCodeAt(0)) % r; 
        //hs += (pPow[i + 1] * text[i].charCodeAt(0)) % r;
    }
    return hs;
}
 
function hash(string, subString)
{
    var comparsions = 0;
    var collisions = 0;
    var stringLength = string.length;
    var subStringLength = subString.length;
    var r = 1000000007;
    var entries = [];
    var p = 2;
    var pPow = [1];
    for (var i = 1; i <= subStringLength; i++)
    {
        pPow.push(pPow[i - 1] * p);
    }
    //var substringtext = string;
    var substringtext = string.substring(0,subStringLength);
    var stringHash = countHash(substringtext, pPow, r);
    var subStringHash = countHash(subString, pPow, r);
    for (var i = 0; i <= stringLength - subStringLength; i++)
    {
        if (subStringHash == stringHash)
        {
            substringtext = string.substring(i, i + subStringLength);
            comparsions++;
            if (substringtext == subString)
            {
                entries.push(i);
            }
            else
            {
                collisions++;
            }
        }
        if (i == stringLength - subStringLength)
        {
            break;
        }
        var hoard = string[i].charCodeAt(0) * pPow[subStringLength - 1] % r;
        hoard = (stringHash - hoard) % r;
        hoard = 2 * hoard % r;
        hoard = (hoard + string[i + subStringLength].charCodeAt(0)) % r;
        stringHash = hoard;
        //hashText = (((hashText - (text[i].charCodeAt(0) * pPow[stringLength - 1]) % r) * 2) % r + text[i + stringLength].charCodeAt(0)) % r;
    }
    var output = [entries, collisions, comparsions]
    return output;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.05.2019, 15:50
Ответы с готовыми решениями:

Поиск подстроки в строке
Всем добрый день. Не могу разобраться вот с этим: var str = 'dankensiedarannichtsistwahr'; console.log('lastIndexOf' + ' ' +...

Есть ли метод поиска по тегам в []?
Приветствую! Задача выловить из страницы форума текст, находящийся под спойлером. Текст заключен в &quot;форумный&quot; тег . ...

Функции поиска элемента в строке
1. Написать функцию isSymbolPresentInString(str,symbol) - возврает true если символ найден в строке и false если нет. ...

18
131 / 146 / 19
Регистрация: 19.02.2017
Сообщений: 619
01.05.2019, 16:13
Такой код тяжело понять. Слишком много изменяемого состояния. Функция hash слишком большая. Как работает ваша функция, есть же стандартный метод поиска подстроки indexOf()?
0
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59
01.05.2019, 17:03  [ТС]
Метод основан на алгоритме Рабина — Карпа

Добавлено через 44 секунды
Что означает фраза слишком много изменяемого состояния?
0
Эксперт JSЭксперт HTML/CSS
2151 / 1496 / 651
Регистрация: 16.04.2016
Сообщений: 3,696
01.05.2019, 18:13
Цитата Сообщение от Inochiron Посмотреть сообщение
Но если подстрока 24 символа и длиннее, метод перестаёт работать
приведите пример строки и подстроки при которых наблюдается трабл. Потестил - проблемы не увидел.
Кстати, а почему был выбран именно этот алгоритм?
У Кнута(и иже с ним) асимптотика линейная. Не кажется ли Вам предпочтительнее?

А в движке V8 например используется алгоритм семейства Бойера - Мура - https://github.com/v8/v8/blob/... g-search.h

А вот в лисе вообще оптимизированный наивный вариант, используемый в спецификации ECMA - https://dxr.mozilla.org/mozill... String.cpp (ищите Note that the spec algorithm has been optimized to avoid building a string in the case where no escapes are present.)

В вебките - поиск ведется регулярками, что кажется идиотизмом(ищем stringProtoFuncSearch) - https://trac.webkit.org/browse... totype.cpp
0
566 / 465 / 183
Регистрация: 14.10.2017
Сообщений: 1,259
01.05.2019, 18:18
а зачем такая сложная функция? можно же гораздо проще написать свою
0
Эксперт JSЭксперт HTML/CSS
2151 / 1496 / 651
Регистрация: 16.04.2016
Сообщений: 3,696
01.05.2019, 18:22
klopp, приветствую
Цитата Сообщение от klopp Посмотреть сообщение
можно же гораздо проще написать свою
с использованием нативных методов, реализованных на основе этих алгоритмов

Но да, правда Ваша - в контексте JS это несколько бредовая идея - реализовать то, что УЖЕ сделано (на уровне языка платформы) и собственно упаковано в метод.
0
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59
01.05.2019, 20:15  [ТС]
У меня стоит учебная задача реализовать этот алгоритм на этом языке

Добавлено через 5 минут
Qwerty_Wasd, Алгоритм не работает, например, при попытке найти строку ""Danny cursed Rivera openly, and forced him, while Rivera danced away"" в рассказе Мексиканец Джека Лондона

Добавлено через 6 минут
Edzard, Можете объяснить, что значит фраза слишком много изменяемого состояния.
0
131 / 146 / 19
Регистрация: 19.02.2017
Сообщений: 619
01.05.2019, 20:23
Цитата Сообщение от Inochiron Посмотреть сообщение
Можете объяснить, что значит фраза слишком много изменяемого состояния.
Много присваиваний.
0
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59
01.05.2019, 20:40  [ТС]
Edzard, А это плохо?
0
131 / 146 / 19
Регистрация: 19.02.2017
Сообщений: 619
01.05.2019, 20:53
Цитата Сообщение от Inochiron Посмотреть сообщение
А это плохо?
Ну вообще чем меньше изменяемого состояния, тем легче понимать код, и меньше ошибок.
0
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59
01.05.2019, 20:58  [ТС]
Edzard, Понятно, просто я не знаю, как можно обойтись меньшим количеством присваиваний
0
566 / 465 / 183
Регистрация: 14.10.2017
Сообщений: 1,259
02.05.2019, 00:53
Цитата Сообщение от Inochiron Посмотреть сообщение
в рассказе Мексиканец Джека Лондона
ну и как вы к тексту обращались?
0
Эксперт JSЭксперт HTML/CSS
2151 / 1496 / 651
Регистрация: 16.04.2016
Сообщений: 3,696
02.05.2019, 01:41
klopp, у ТС и правда некорректно код работает на больших объемах. Плюс некорректно соблюдены условия, присмотритесь к ситуации с 31 строки по 49. Только сильно не вникайте, а то рефлекторно плюнете в монитор - потом отмывать

Inochiron, короче если править именно Ваш код, при этом сократив вакханалию лишних объявлений, то - https://codepen.io/qwerty_wasd/pen/vMqZrg

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let opRK = {
  getHash: (text, pPow, r) => {
    let hash = 0;
    for(let i = 0; i < text.length; i++) hash += (pPow[text.length - 1 - i] * text[i].charCodeAt(0)) % r;
    return hash;
  },
  getMatches: (string, subString) => {
    let opTmp = {
      collisions: 0,
      r: 101,
      entries: [],
      pPow: [1],
      substringtext:string.substring(0,subString.length),
    };
    
    for (let i = 1; i <= subString.length; i++) opTmp.pPow.push(opTmp.pPow[i - 1] * 2);
    
    opTmp.stringHash = opRK.getHash(opTmp.substringtext, opTmp.pPow, opTmp.r);
    opTmp.subStringHash = opRK.getHash(subString, opTmp.pPow, opTmp.r);
    
    for (let i = 0; i < string.length - subString.length; i++) {
      if (opTmp.subStringHash !== opTmp.stringHash) {
        (opTmp.substringtext === subString) ? opTmp.entries.push(i - 1) : opTmp.collisions++;
        opTmp.substringtext = string.substring(i, i + subString.length);
      }
      opTmp.stringHash = (((2 * ((opTmp.stringHash - (string[i].charCodeAt(0) * opTmp.pPow[subString.length - 1] % opTmp.r)) % opTmp.r) % opTmp.r) + string[i + subString.length].charCodeAt(0)) % opTmp.r);
    }
    return [opTmp.entries, opTmp.collisions, opTmp.entries.length];
  }
};
Кстати про объявления... заметил что у многих изучающих JS, особенно у тех кто пришел с низкоуровневых языков, помимо прочего, есть прям мания какая-то - получать в отдельную переменную длину массива\коллекции\строки......... Не сходите с ума Вы кодите в JS. Это свойство уже при создании каждого из описанных экземпляров присутствует и посчитано. Будьте уверены - оно инициализировано.
Убедится в этом можно просто проверив наличие этого свойства -
JavaScript
1
2
3
4
5
6
7
8
9
10
const listAllProperties = o => {     
  let objectToInspect, result = [];
  for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect))
    result = result.concat(Object.getOwnPropertyNames(objectToInspect));
  return result;
}
console.log(listAllProperties(`abc`));
/*
["0", "1", "2", "length", "length", "constructor", "anchor", "big", "blink", "bold", "charAt", "charCodeAt", "codePointAt", "concat", "endsWith", "fontcolor", "fontsize", "fixed", "includes", "indexOf", "italics", "lastIndexOf", "link", "localeCompare", "match", "normalize", "padEnd", "padStart", "repeat", "replace", "search", "slice", "small", "split", "strike", "sub", "substr", "substring", "sup", "startsWith", "toString", "trimStart", "trimLeft", "trimEnd", "trimRight", "toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase", "toUpperCase", "valueOf", "matchAll", "trim", "constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]
*/
0
566 / 465 / 183
Регистрация: 14.10.2017
Сообщений: 1,259
02.05.2019, 01:49
Цитата Сообщение от Qwerty_Wasd Посмотреть сообщение
с использованием нативных методов, реализованных на основе этих алгоритмов
вовсе нет, можно, например, так
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const searchSubstring = (str, substr) => {
    let res = [];
    for(let i = 0; i < str.length; i++){
        if(substr[0] == str[i]){
            for(let j = i + 1, k = 1; j < str.length && k < substr.length; j++, k++){
                if(substr[k] != str[j])
                    break;
                if(k == substr.length - 1){
                    res.push([i, j]);
                }
            }
        }
    }
    if(!res.length)
        return false;
    return res;
}
функция возвращает массив, в котором каждый вложенный массив имеет два числа- индексы начала и конца искомой подстроки в строке. Индекс конца может и излишне, но пусть будет)))
Осталось добавить "защиту от дурака".
0
02.05.2019, 01:52

Не по теме:

klopp,

Цитата Сообщение от klopp Посмотреть сообщение
вовсе нет
нуууу.... едрен батон. Я думал Вы поняли шутку :)

0
02.05.2019, 01:54

Не по теме:

Цитата Сообщение от Qwerty_Wasd Посмотреть сообщение
Я думал Вы поняли шутку :)
туплю наверное, спать пора, футбол смотрел)))

0
02.05.2019, 01:57

Не по теме:

klopp, тогда спокойной ночи :)

0
1 / 1 / 0
Регистрация: 22.03.2019
Сообщений: 59
02.05.2019, 09:04  [ТС]
klopp, Я обращался к тексту в node.js таким образом:
JavaScript
1
2
3
var fs = require("fs"); 
var text = fs.readFileSync("string.txt", "utf8");
var substring = fs.readFileSync("subString.txt", "utf8");
Добавлено через 11 минут
Qwerty_Wasd, Ваш код действительно исправил проблему, ещё бы понять как он её исправил

Добавлено через 26 минут
Qwerty_Wasd, Алгоритм должен сравнивать строки посимвольно только, если строки равны.
JavaScript
1
2
3
4
5
    for (let i = 0; i < string.length - subString.length; i++) {
      if (opTmp.subStringHash !== opTmp.stringHash) {
        (opTmp.substringtext === subString) ? opTmp.entries.push(i - 1) : opTmp.collisions++;
        opTmp.substringtext = string.substring(i, i + subString.length);
      }
Добавлено через 39 секунд
*, если хэши равны
0
Эксперт JSЭксперт HTML/CSS
2151 / 1496 / 651
Регистрация: 16.04.2016
Сообщений: 3,696
02.05.2019, 14:23
Цитата Сообщение от Inochiron Посмотреть сообщение
Алгоритм должен сравнивать строки посимвольно только
Он посимвольно убирает из opTmp.substringtext первый символ, потом сравниваются строки(законсольте opTmp.substringtext в цикле). При этом хеши не должны быть равны. Иначе по наступлению такого равенства цикл просто прекратится на первом же совпадении, при этом показав неверный результат.

Добавлено через 50 секунд
JavaScript
1
2
3
4
5
6
7
8
9
10
for (let i = 0; i < string.length - subString.length; i++) {
      if (opTmp.subStringHash == opTmp.stringHash) {
        (opTmp.substringtext === subString) ? opTmp.entries.push(i - 1) : opTmp.collisions++;
        opTmp.substringtext = string.substring(i, i + subString.length);
        console.log(opTmp.substringtext);
      }
      opTmp.stringHash = (((2 * ((opTmp.stringHash - (string[i].charCodeAt(0) * opTmp.pPow[subString.length - 1] % opTmp.r)) % opTmp.r) % opTmp.r) + string[i + subString.length].charCodeAt(0)) % opTmp.r);
    }
// "Danny cursed Rivera openly, and forced him, while Rivera danced away."
 // [[-1], 0, 1]
Цитата Сообщение от Inochiron Посмотреть сообщение
Qwerty_Wasd, Ваш код действительно исправил проблему, ещё бы понять как он её исправил
Учитесь переводить код на человеческий. Это очень сильно поможет избежать логических ошибок.

Если глаз режет здесь, в песочнице повторил
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// создадим, вместо туевы хучи переменных в глобальной области, один операционный объект.
// Потребление памяти это несильно сократит. Но зато уменьшит кол-во обращений к ней.
// А также предотвратит возможные коллизии до 1.
// А вообще, если Вы посчитали что чувствуете себя достаточно комфортно в Node,
// пора бы уже и модули писать.  Я именно эту конечную модель сейчас показываю.
// let module = require(`opRK`); <- module получит объект, что продемонстрирован ниже
let opRK = {
  // метод объекта
  // получим хеш со строки
  // на будущее - лучше использовать алгоритмы хешей Бернштейна
  // или же один из  Кернигана и Ритчи
  // быстрее них только свет.
  getHash: (text, pPow, r) => {
    let hash = 0;
    for(let i = 0; i < text.length; i++) hash += (pPow[text.length - 1 - i] * text[i].charCodeAt(0)) % r;
    return hash;
  },
  // помимо Рабина-Карпа
  // лучше бы Вы сразу Кнута — Морриса — Пратта поизучали
  getMatches: (string, subString) => {
    // опять вместо же кучи переменных - операционный объект
    let opTmp = {
      // инициализируем поля
      // ложные срабатывания
      collisions: 0,
      // Простое число для хеша
      r: 101,
      // массив вхождений
      entries: [],
      // массив зерен\солек\семян (на вкус) 
      pPow: [1],
      // начальный кусок с которым будет сравниваться подстрока
      substringtext:string.substring(0,subString.length),
    };
    
    // пробежимся по подстроке и с каждого символа
    // потырим зернышко в opTmp.pPow
    for (let i = 1; i <= subString.length; i++) opTmp.pPow.push(opTmp.pPow[i - 1] * 2);
    
    // Получим хеши искомой и наблюдаемой строк
    opTmp.stringHash = opRK.getHash(opTmp.substringtext, opTmp.pPow, opTmp.r);
    opTmp.subStringHash = opRK.getHash(subString, opTmp.pPow, opTmp.r);
        
    for (let i = 0; i < string.length - subString.length; i++) {
      // пока хеши не равны
      if (opTmp.subStringHash !== opTmp.stringHash) {
        // тернарный оператор
        // если строки совпали
        // пополняем массив вхождений
        // иначе коллизия
        // тут бы Вам кстати по-другому сделать надо было,
        // но это Вы уже сами подумаете
        // (подсказка - тернарный оператор может продолжаться сколь угодно долго при семантике)
        // (подсказка - ложные срабатывания можно в принципе определить как
        // opTmp.substringtext[0] === subString[0]
        (opTmp.substringtext === subString) ? opTmp.entries.push(i - 1) : opTmp.collisions++;
        // получили что хотели
        // смещаем на один символ шаблон
        opTmp.substringtext = string.substring(i, i + subString.length);
      }
      // и меняем хеш
      // идея сделать именно так .....
      // ну ладно Вам виднее
      // подсказка(у вас уже готов целый метод)
      opTmp.stringHash = (((2 * ((opTmp.stringHash - (string[i].charCodeAt(0) * opTmp.pPow[subString.length - 1] % opTmp.r)) % opTmp.r) % opTmp.r) + string[i + subString.length].charCodeAt(0)) % opTmp.r);
    }
    // ну и собственно вернем результаты [массив вхождений, ложные, кол-во вхождений]
    return [opTmp.entries, opTmp.collisions, opTmp.entries.length];
  }
};
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.05.2019, 14:23
Помогаю со студенческими работами здесь

Ошибка при поиска символа '/' в строке
Здравствуйте. Начал изучать Web-программирование. Есть страничка, в ней вставка javascript. В этой вставке обрабатывается строка. Всю...

Функция поиска подстроки в строке
int CChar::strpos(char* sub, char* str) { char* temp = new char; int t=0; for(int i=0; i&lt;strlen(str); i++) { ...

Алгоритмы поиска подстроки в строке
Если не сложно, помогите пожалуйста и простенько объясните алгоритмы поиска последовательного прямого поиска, Рабина, Кнута-Морриса-Пратта...

Алгоритм поиска подстроки в строке.
1. Каким образом ищется подстрока, если использовать стандартную функцию pos? 2. Какой лучший алгоритм поиска подстроки при следующих...

Реализация алгоритмов поиска подстроки в строке
Реализация алгоритмов поиска подстроки в строке. Реализовать любые два алгоритма поиска. Исходные данные-текстовый файл, содержащий...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru