Я хочу узнать, содержит ли строка слово-палиндром. Например, hellosannasmith содержит слово-палиндром и должно вернуть sannas, однако givemefood должно вернуть none. Сначала я попробовал это с помощью 2 циклов for, затем начал думать, почему бы не использовать цикл while, но прежде чем я начну идти по маршруту цикла while, я хочу посмотреть, можно ли это сделать сначала с помощью 2 циклов for.
Мне удалось поместить san в новую строковую переменную палиндрома, но я не уверен, что еще я здесь упускаю или упускаю из виду. Любая помощь будет принята с благодарностью.
function SearchingChallenge(str) {
var palindromeStr = "";
for (var i = 0; i < str.length / 2; i++) {
for (var j = str.length - 1; str.length / 2 < j; j--) {
if (str[i + 1] == str[j - 1] && str[i] == str[j]) {
palindromeStr += str[i];
}
}
}
if (palindromeStr == "") {
return "none";
}
return palindromeStr;
}
console.info(SearchingChallenge('hellosannasmith'));
console.info(SearchingChallenge('givemefood'));@mykaf Я использую ручку и бумагу, чтобы визуализировать результат, и пришел к выводу, что условие if можно исправить на что-то «лучшее», но пока не знаю, как к этому подойти
Это не тот же вопрос, что и дубликат. Есть более эффективные способы, чем проверка того, является ли каждая отдельная подстрока палиндромом.
@DonDavid12 DonDavid12 Какое здесь определение слова? Любая строка длиной не менее 2?
Это не было указано в задаче задачи, но да, давайте пока остановимся на этом @Unmitigated
Вам нужно найти самую длинную палиндромную подстроку или любую?
Предполагая, что в подстроке @Unmitigated имеется один палиндром
@ DonDavid12 Однако в 'hellosannasmith' есть еще один палиндром: 'll'.
@Unmitigated При рассмотрении двухбуквенных слов. А еще: nn и anna кстати.
@KooiInc Да, это правда. В итоге я просто реализовал метод поиска самой длинной палиндромной подстроки.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете определить Set(), включая все слова, а затем использовать динамическое программирование, чтобы найти самый длинный палиндром.
Вы также можете добавить некоторые условия для возврата палиндрома, найденного в наборе. (Из вопроса неясно).
const words = new Set(["hello", "sannas", "smith", "give", "me", "food"]);
function SearchingChallenge(str) {
const n = str.length;
if (n === 0) return "none";
let res = "";
const dp = Array.from({ length: n }, () => Array(n).fill(false));
for (let len = 1; len <= n; len++) {
for (let i = 0; i <= n - len; i++) {
const j = i + len - 1;
if (len === 1) {
dp[i][j] = true;
} else if (len === 2) {
dp[i][j] = str[i] === str[j];
} else {
dp[i][j] = str[i] === str[j] && dp[i + 1][j - 1];
}
if (dp[i][j] && len > res.length) {
res = str.slice(i, j + 1);
}
}
}
return words.has(res) ? res : "none";
}
console.info(SearchingChallenge("hellosannasmith"));
console.info(SearchingChallenge("givemefood"));Следует учитывать, что ваш внешний цикл просматривает только первую половину строки, а внутренний цикл просматривает только вторую половину строки, то есть вы не проверяете все возможные подстроки. Ваш подход учитывает только то, существует ли он в центре строки.
Еще одно замечание: ваше условие if (str[i + 1] == str[j - 1] && str[i] == str[j]) проверяет только пары символов в указанной позиции. Таким образом, вы выполняете частичную проверку символов, а не всю подстроку. Таким образом, вы в конечном итоге строите свою строку, когда совпадают две пары, что не гарантирует, что это палиндром.
Попробуйте сделать его более читабельным и надежным, изменив циклы:
for (let i = 0; i < str.length; i++) {
for (let j = i + 1; j <= str.length; j++) {
Затем вы можете построить свою подстроку, используя эти индексы
Во-первых, сравнивая str[i] = str[j] вы можете прийти к «палиндрому», не имея палиндрома. визуализация «abcdefcba»: для i=1,2,3, j=n-1,n-2,n-3 str[i] === str[j]. однако они не связаны, потому что между ними есть другие вещи.
Во-вторых, в той же проверке, которую вы проверяете как str[i]===str[j], так и str[i+1]===str[j-1], это означает, что последний символ, отвечающий критериям, не будет вводить результат (кроме случая, когда они встречаются в центре, как в вашем первом примере)
Итак, вам нужно для каждого заданного интервала проверять, является ли подстрока в данном интервале палиндромом.
Проверьте приведенный ниже пример:
function isPalindrome(str) {
return str === str.split('').reverse().join('');
}
function SearchingChallenge(str) {
if (str.length <= 1) return 'none';
for(let i=0;i<str.length-3;i++) {
for(let j=str.length-1; j>i+2; j--) {
const substr = str.substring(i, j);
if (isPalindrome(substr)) return substr;
}
}
return 'none';
}
console.info(SearchingChallenge('hellosannasmith'));
console.info(SearchingChallenge('givemefood'));
console.info(SearchingChallenge('abcdef'));
console.info(SearchingChallenge('someawesomeemosik'));И наконец, помните две вещи:
givemefood, eme - это палиндром. в приведенном выше примере минимальная длина палиндрома установлена на треть. но это нужно определитьЭто помогает, но я пытаюсь понять, почему во втором цикле мы решили использовать j>i+2 и почему в данном случае выбрали +2?
Можете ли вы исправить повторяющиеся ошибки в написании слова «палиндром»?
@ DonDavid12 DonDavid12 это связано со вторым пунктом, который я указал в конце. Вопрос в том, какова минимальная длина палиндрома, который вы считаете палиндромом. в моем примере я установил 3 буквы. Для этого мне нужно, чтобы каждая подстрока, которую я проверяю, содержала как минимум 3 буквы, то есть j-i >=3 или j-i>2.
Вы можете просто использовать алгоритм Манахера, чтобы найти самую длинную палиндромную подстроку за линейное время (O(N)) по количеству символов в строке.
function findLongestPalindromeSubstring(str) {
const pOdd = Array(str.length).fill(0), pEven = Array(str.length).fill(0);
let lOdd = 0, rOdd = 0, lEven = 0, rEven = 0, maxLen = 0, start = 0;
for (let i = 0; i < str.length; i++) {
if (rOdd > i) pOdd[i] = Math.min(rOdd - i, pOdd[lOdd + rOdd - i]);
while (i - pOdd[i] >= 0 && i + pOdd[i] < str.length &&
str[i - pOdd[i]] === str[i + pOdd[i]]) ++pOdd[i];
if (i + pOdd[i] > rOdd) lOdd = i - pOdd[i], rOdd = i + pOdd[i];
if (2 * pOdd[i] - 1 > maxLen) {
maxLen = 2 * pOdd[i] - 1;
start = i - pOdd[i] + 1;
}
if (rEven > i) pEven[i] = Math.min(rEven - i, pEven[lEven + rEven - i + 1]);
while (i - 1 - pEven[i] >= 0 && i + pEven[i] < str.length
&& str[i - 1 - pEven[i]] === str[i + pEven[i]]) ++pEven[i];
if (i + pEven[i] > rEven) lEven = i - 1 - pEven[i], rEven = i + pEven[i];
if (2 * pEven[i] > maxLen) {
maxLen = 2 * pEven[i];
start = i - pEven[i];
}
}
return maxLen > 1 ? str.slice(start, start + maxLen) : 'none';
}
console.info(findLongestPalindromeSubstring('hellosannasmith'));
console.info(findLongestPalindromeSubstring('givemefood'));
console.info(findLongestPalindromeSubstring('abc'));> просто используйте 9 локальных привязок, несколько вложенных циклов, 14 условных операторов, 13 мутаций и еще один цикл для наглядности!
чтобы улучшить этот ответ, я думаю, вам следует связать алгоритм и включить базовое объяснение того, как он работает. Я поклонник оператора запятой, но мне интересно, почему он применяется непоследовательно? То есть, почему некоторые консеквенты if получают ,, тогда как другие получают { ...; ...; }?
@Мулан, я ценю обратную связь. Оглядываясь назад, возможно, слово «простой» было неправильным; В основном я имел в виду, что это стандартный метод эффективного решения большинства задач палиндрома. Что касается неиспользования везде оператора запятой, я старался избежать чрезмерной горизонтальной прокрутки в фрагменте кода. Кроме того, я написал этот код по памяти, не следуя конкретной статье. Я мог бы дать ссылку на страницу Википедии, но там используется слегка измененная версия алгоритма.
Я думаю, что проблема, которую вы описываете, заключается в следующем Самая длинная палиндромная подстрока
У меня нет javascript, но вот для Java
public String longestPalindrome(String s) {
int n = s.length();
int maxLen = 0;
int maxL = 0;
int maxR = 0;
for (int i = 0; i < n ; i++) {
int l = i, r = i;
while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
int len = r-l+1;
if (len > maxLen) {
maxLen = len;
maxL = l;
maxR = r;
}
l--;
r++;
}
l = i; r = i + 1;
while (l >= 0 && r < n && s.charAt(l) == s.charAt(r)) {
int len = r-l+1;
if (len > maxLen) {
maxLen = len;
maxL = l;
maxR = r;
}
l--;
r++;
}
}
return s.substring(maxL, maxR+1);
}
Строка может содержать несколько палиндромов. Вот функция, которая может вернуть их все (массив) или просто подтвердить наличие палиндрома в заданной строке (истина/ложь). Перед проверкой входная строка преобразуется в строку, содержащую только [a-zA-Z] (таким образом, все пробелы, вставки и т. д. удаляются).
Поиграйте с этим кодом (более проработанной версией) @Stackblitz
const strings = JSON.parse(document.querySelector(`#strings`)
.content.textContent);
const result = document.querySelector(`#result`);
// just check for palindrome existence
strings.forEach(string => {
const found = getPalindromesInString({str2Check: string, single: true});
result.innerHTML += `<b>Are there palindromes in</b>\n<i>${
JSON.stringify(string)}</i>?<span>${
found.error
? ` => ${found.error}` : found ? ` => SURE` : ` => NOPE`}
</span>\n`;
});
result.innerHTML += `<hr>`;
// retrieve all palindromes
strings.forEach(string => {
const found = getPalindromesInString({str2Check: string});
result.innerHTML += [
`<b>All palindromes in</b>\n<i>${JSON.stringify(string)}</i>`,
`${JSON.stringify(found, null, 2)}`]
.join(`\n`) + `\n\n`;
});
function getPalindromesInString({
str2Check,
caseSensitive = false,
single = false,
isPalindrome = stringIsPalindromeFactory() } = {}) {
if ( str2Check?.constructor !== String || str2Check?.length <= 1 ) {
return {error: `invalid input`};
}
str2Check = str2Check.replace(/[^a-z]/gi, ``);
const result = [];
for (let i = 0; i < str2Check.length; i += 1) {
for (let j = str2Check.length; j > i + 2; j -= 1) {
const substr = str2Check.substring(i, j);
const palindromeFound = substr.length > 1
&& isPalindrome(substr, caseSensitive);
palindromeFound && result.push(substr);
}
}
return single ? result.length > 0 : result;
}
// Recursive palindrome determination
function stringIsPalindromeFactory() {
return function maybePalindrome(string, cs = false) {
const lc = cs ? string : string?.toLowerCase();
return lc[0] !== lc.at(-1) ? false : tail(lc.slice(1, -1));
};
function tail(str) {
return !str.length
? true : str[0] !== str.slice(-1)
? false : tail(str.slice(1, -1));
};
}b {color: green; }
i {
display: inline-block;
margin-left: 1rem;
color: blue;
}
span {color: red; }<template id = "strings">[
"I don't think we'll find palindromes",
"It's Anna I am talking about, or quod non so m eawe so meem sos and finally tattarrattat",
"A man, a plan, a canal: Panama",
"T. Eliot, top bard, notes putrid tang emanating, is sad; I'd assign it a name: gnat dirt upset on drab pot toilet.",
{"invalid": "input"} ]
</template>
<pre id = "result"></pre>
Какие шаги вы предприняли для устранения этой проблемы?