bool wordBreak(string s, unordered_set<string>& wordDict) { int len = s.length(); if (len == 0) return false; vector<bool> isBreakable(len+1, false); isBreakable[len] = true; int minLen = INT_MAX, maxLen = INT_MIN; for (string word : wordDict) { minLen = min(minLen, (int)word.length()); maxLen = max(maxLen, (int)word.length()); } for (int i = len - minLen; i >= 0; --i) { for (int j = minLen; j <= min(maxLen, len - i); ++j) { if (isBreakable[i + j] && wordDict.count(s.substr(i, j))) { isBreakable[i] = true; break; } } } return isBreakable[0]; }
std::unique_ptr<Lines> createLines(RenderBlockFlow& flow) { auto lines = std::make_unique<Lines>(); RenderText& textRenderer = toRenderText(*flow.firstChild()); ASSERT(!textRenderer.firstTextBox()); const RenderStyle& style = *flow.style(); const unsigned textLength = textRenderer.textLength(); float wordTrailingSpaceWidth = style.font().width(TextRun(&space, 1)); LazyLineBreakIterator lineBreakIterator(textRenderer.text(), style.locale()); int nextBreakable = -1; unsigned lineEndOffset = 0; while (lineEndOffset < textLength) { lineEndOffset = skipWhitespaces(textRenderer, lineEndOffset, textLength); unsigned lineStartOffset = lineEndOffset; unsigned runEndOffset = lineEndOffset; LineWidth lineWidth(flow, false, DoNotIndentText); while (runEndOffset < textLength) { ASSERT(!isWhitespace(textRenderer.characterAt(runEndOffset))); bool previousWasSpaceBetweenRuns = runEndOffset > lineStartOffset && isWhitespace(textRenderer.characterAt(runEndOffset - 1)); unsigned runStartOffset = previousWasSpaceBetweenRuns ? runEndOffset - 1 : runEndOffset; ++runEndOffset; while (runEndOffset < textLength) { if (runEndOffset > lineStartOffset && isBreakable(lineBreakIterator, runEndOffset, nextBreakable, false)) break; ++runEndOffset; } unsigned runLength = runEndOffset - runStartOffset; bool includeEndSpace = runEndOffset < textLength && textRenderer.characterAt(runEndOffset) == ' '; float wordWidth; if (includeEndSpace) wordWidth = textWidth(textRenderer, runStartOffset, runLength + 1, lineWidth.committedWidth(), style) - wordTrailingSpaceWidth; else wordWidth = textWidth(textRenderer, runStartOffset, runLength, lineWidth.committedWidth(), style); lineWidth.addUncommittedWidth(wordWidth); if (!lineWidth.fitsOnLine()) { if (!lineWidth.committedWidth()) { lineWidth.commit(); lineEndOffset = runEndOffset; } break; } lineWidth.commit(); lineEndOffset = runEndOffset; runEndOffset = skipWhitespaces(textRenderer, runEndOffset, textLength); } if (lineStartOffset == lineEndOffset) continue; Line line; line.textOffset = lineStartOffset; line.textLength = lineEndOffset - lineStartOffset; line.width = lineWidth.committedWidth(); lines->append(line); } textRenderer.clearNeedsLayout(); lines->shrinkToFit(); return lines; }
std::unique_ptr<Layout> create(RenderBlockFlow& flow) { RenderText& textRenderer = toRenderText(*flow.firstChild()); ASSERT(!textRenderer.firstTextBox()); const RenderStyle& style = flow.style(); const unsigned textLength = textRenderer.textLength(); ETextAlign textAlign = style.textAlign(); float wordTrailingSpaceWidth = style.font().width(TextRun(&space, 1)); LazyLineBreakIterator lineBreakIterator(textRenderer.text(), style.locale()); int nextBreakable = -1; Layout::RunVector runs; unsigned lineCount = 0; unsigned lineEndOffset = 0; while (lineEndOffset < textLength) { lineEndOffset = skipWhitespaces(textRenderer, lineEndOffset, textLength); unsigned lineStartOffset = lineEndOffset; unsigned wordEndOffset = lineEndOffset; LineWidth lineWidth(flow, false, DoNotIndentText); Vector<Run, 4> lineRuns; lineRuns.uncheckedAppend(Run(lineStartOffset, 0)); while (wordEndOffset < textLength) { ASSERT(!isWhitespace(textRenderer.characterAt(wordEndOffset))); bool previousWasSpaceBetweenWords = wordEndOffset > lineStartOffset && isWhitespace(textRenderer.characterAt(wordEndOffset - 1)); unsigned wordStartOffset = previousWasSpaceBetweenWords ? wordEndOffset - 1 : wordEndOffset; ++wordEndOffset; while (wordEndOffset < textLength) { if (wordEndOffset > lineStartOffset && isBreakable(lineBreakIterator, wordEndOffset, nextBreakable, false)) break; ++wordEndOffset; } unsigned wordLength = wordEndOffset - wordStartOffset; bool includeEndSpace = wordEndOffset < textLength && textRenderer.characterAt(wordEndOffset) == ' '; float wordWidth; if (includeEndSpace) wordWidth = textWidth(textRenderer, wordStartOffset, wordLength + 1, lineWidth.committedWidth(), style) - wordTrailingSpaceWidth; else wordWidth = textWidth(textRenderer, wordStartOffset, wordLength, lineWidth.committedWidth(), style); lineWidth.addUncommittedWidth(wordWidth); // Move to the next line if the current one is full and we have something on it. if (!lineWidth.fitsOnLine() && lineWidth.committedWidth()) break; if (wordStartOffset > lineEndOffset) { // There were more than one consecutive whitespace. ASSERT(previousWasSpaceBetweenWords); // Include space to the end of the previous run. lineRuns.last().textLength++; lineRuns.last().right += wordTrailingSpaceWidth; // Start a new run on the same line. lineRuns.append(Run(wordStartOffset + 1, lineRuns.last().right)); } lineWidth.commit(); lineRuns.last().right = lineWidth.committedWidth(); lineRuns.last().textLength = wordEndOffset - lineRuns.last().textOffset; lineEndOffset = wordEndOffset; wordEndOffset = skipWhitespaces(textRenderer, wordEndOffset, textLength); if (!lineWidth.fitsOnLine()) { // The first run on the line overflows. ASSERT(lineRuns.size() == 1); break; } } if (lineStartOffset == lineEndOffset) continue; adjustRunOffsets(lineRuns, textAlign, lineWidth.committedWidth(), lineWidth.availableWidth()); for (unsigned i = 0; i < lineRuns.size(); ++i) runs.append(lineRuns[i]); runs.last().isEndOfLine = true; ++lineCount; } textRenderer.clearNeedsLayout(); return Layout::create(runs, lineCount); }
bool Arbitre::checkWinner(Vector<int> const &pos, char const * const *map, int color, bool recusive) { int nb; Vector<int> next = pos; if (((color == BLACK ? _prisoner[0] : _prisoner[1])) >= 10) { _isWinner = true; _winner = color; return true; } nb = 1; ++next.x; while (next.x < 19 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); ++next.x; ++nb; } next.x = pos.x - 1; while (next.x >= 0 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); --next.x; ++nb; } if (nb >= 5) { ++next.x; if (_ruleOptionalEnd == false) { _isWinner = true; return true; } else if (_ruleOptionalEnd == true && isBreakable(next, map, color, nb, Vector<int>(1, 0)) == false) { _isWinner = true; return true; } } nb = 1; next.x = pos.x; next.y = pos.y + 1; while (next.y < 19 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); ++next.y; ++nb; } next.y = pos.y - 1; while (next.y >= 0 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); --next.y; ++nb; } if (nb >= 5) { ++next.y; if (_ruleOptionalEnd == false) { _isWinner = true; return true; } else if (_ruleOptionalEnd == true && isBreakable(next, map, color, nb, Vector<int>(0, 1)) == false) { _isWinner = true; return true; } } nb = 1; next.x = pos.x + 1; next.y = pos.y + 1; while (next.x < 19 && next.y < 19 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); ++next.x; ++next.y; ++nb; } next.x = pos.x - 1; next.y = pos.y - 1; while (next.x >= 0 && next.y >= 0 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); --next.x; --next.y; ++nb; } if (nb >= 5) { ++next.x; ++next.y; if (_ruleOptionalEnd == false) { _isWinner = true; return true; } else if (_ruleOptionalEnd == true && isBreakable(next, map, color, nb, Vector<int>(1, 1)) == false) { _isWinner = true; return true; } } nb = 1; next.x = pos.x - 1; next.y = pos.y + 1; while (next.x >= 0 && next.y < 19 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); --next.x; ++next.y; ++nb; } next.x = pos.x + 1; next.y = pos.y - 1; while (next.x < 19 && next.y >= 0 && map[next.y][next.x] == color) { if (recusive) checkWinner(next, map, color, false); ++next.x; --next.y; ++nb; } if (nb >= 5) { --next.x; ++next.y; if (_ruleOptionalEnd == false) { _isWinner = true; return true; } else if (_ruleOptionalEnd == true && isBreakable(next, map, color, nb, Vector<int>(-1, 1)) == false) { _isWinner = true; return true; } } return (false); }