本文へスキップ
製品デスクトップツールTASTECAD図面の確認TASTEFILESファイル管理TASTEFTPファイル転送TASTESSHリモートワークスペースTASTEZIP圧縮と展開開発ツールTASTECODERust 統合開発環境TASTESTUDIO統合開発・テスト環境TASTEETLデータ統合(ETL)サーバーTASTEREMOTEリモートデスクトップサーバーTASTEGEO空間情報サーバーTASTEMAILメールワークスペースはじめるダウンロードドキュメント購入すべての製品
マーケットプレイス
ニュース
技術ニュース今日の開発ニュース開発ドキュメントプログラミング言語RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDartWebフロントエンド フレームワークNext.jsReactVue.js · NuxtSvelteKitAngularサーバー フレームワークSpring BootDjangoFastAPIASP.NET CoreNestJS · Expressアプリ・デスクトップ フレームワークTauriFlutterReact NativeElectronアルゴリズムアルゴリズムの基礎主要アルゴリズム発展アルゴリズム実務のアルゴリズム
コミュニティプロジェクト開発ログプロンプトAIツールの問題ショーケースコミュニティガイド
協業技術移転ウェブサイト構築デスクトップアプリ構築リリース・決済パイプライン販売パートナーお問い合わせ
サービスリモートデスクトップインストールパッケージのカスタマイズ
TASTEDEV
製品

デスクトップツール

TASTECAD複雑な図面を、軽やかにひらくTASTEFILES必要なファイルだけを、最速でTASTEFTPファイルが行き交う、いちばん端正な道TASTESSHサーバーとあなたを、より確かにつなぐTASTEZIPより速くまとめ、より安全にひらく

開発ツール

TASTECODERust アプリの編集・ビルド・デバッグ・テストまでひとつのウィンドウでTASTESTUDIO編集からリモートテスト、承認した AI 修正までTASTEETL値を見ながら、データを運ぶ

サーバー

TASTEREMOTE自社サーバーで運用するリモートデスクトップTASTEGEOGeoServer 互換の空間情報サーバーを Rust で作り直しますTASTEMAILメールの主導権を、もう一度自分の手に

はじめる

ダウンロード全製品の最新版ドキュメント各製品の使い方購入サブスクリプション・永久ライセンスすべての製品全製品を一覧で
すべての製品
マーケットプレイスニュース
技術

ニュース

今日の開発ニュース言語・フレームワーク・GitHub・AI の公式発表開発ドキュメント言語・フレームワーク・アルゴリズムのガイド

プログラミング言語

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

フレームワーク

Webフロントエンド フレームワークNext.jsReactVue.js · NuxtSvelteKitAngular
サーバー フレームワークSpring BootDjangoFastAPIASP.NET CoreNestJS · Express
アプリ・デスクトップ フレームワークTauriFlutterReact NativeElectron

アルゴリズム

アルゴリズムの基礎計算量解析 · ソート · 探索 · 基本データ構造 · 木構造とヒープ主要アルゴリズムグラフ探索 · 最短経路と最小全域木 · 動的計画法 · 貪欲法 · 分割統治法 · バックトラッキング発展アルゴリズム文字列アルゴリズム · 数学と整数論 · ビット演算 · セグメント木 · Union-Find実務のアルゴリズムコーディング面接対策 · LRUキャッシュ · レート制限 · コンシステントハッシュ法
開発ドキュメントをすべて見る
コミュニティ
プロジェクトビルダーと作品を探す開発ログ決定と試行錯誤プロンプト再利用できる指示AIツールの問題Claude・Codex・Gemini の問題と回避策ショーケース完成した成果コミュニティガイドオープンにつくる方法
協業
技術移転Rust・egui でネイティブアプリを作るウェブサイト構築10言語、アカウント、ドキュメントとダウンロードデスクトップアプリ構築Rust・egui、WebView なしリリース・決済パイプライン署名・MSI・deb・rpm・AppImage・ハッシュ販売パートナー紹介して決済額の30%お問い合わせ構築・提携・投資のご相談
サービス
リモートデスクトップブラウザから自分のパソコンへインストールパッケージのカスタマイズ必要な機能だけ、設定は事前に
購入
JA
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
ログイン
ログイン
TASTEDEV

小さなツールから、より良い開発へ。

support@tastedev.netTASTEDEVを支援
製品製品ラインナップ購入ドキュメントダウンロードマーケットプレイスサポート
コミュニティプロジェクト開発ログプロンプトAIツールの問題ショーケース
ポリシープライバシーポリシー利用規約サブスクリプション規約返金ポリシーコミュニティガイドライン
アカウントログイン新規登録
訪問者
今日
012345678901234567890123456789012345678901234567890123456789
昨日
012345678901234567890123456789012345678901234567890123456789
累計閲覧
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
商号
GXSOFT
代表者
CHOI YOUNG GU
事業者登録番号
853-44-00368
所在地
9F V24, 351 Gyeongin-ro, Michuhol-gu, Incheon, Republic of Korea
電話
+82-10-4404-1523
メール
whitecalvin@tastedev.net
個人情報保護責任者
CHOI YOUNG GU

© 2026 TASTEDEV製品情報は検証済みの開発ソースに基づいています。リリース・改善中

文字列アルゴリズム ドキュメント
文字列アルゴリズム
ConceptsHow It WorksImplementationComplexityPractice ProblemsReal-World Use
ディスカッション

文字列アルゴリズム ガイド · 3/6

Implementation

この章は現在、英語でのみ提供しています。

KMP and a trie in Python, explained, then the same KMP core in C++, Java and TypeScript.

Python: KMP

def prefix_function(p: str) -> list[int]:
    pi = [0] * len(p)                    # pi[i]: longest border of p[:i+1]
    k = 0
    for i in range(1, len(p)):
        while k > 0 and p[i] != p[k]:    # fall back to a shorter border
            k = pi[k - 1]
        if p[i] == p[k]:
            k += 1
        pi[i] = k
    return pi


def kmp_search(text: str, pattern: str) -> list[int]:
    m = len(pattern)
    if m == 0:
        return list(range(len(text) + 1))
    pi = prefix_function(pattern)
    hits, k = [], 0                         # k: matched so far
    for i, ch in enumerate(text):
        while k > 0 and ch != pattern[k]:
            k = pi[k - 1]
        if ch == pattern[k]:
            k += 1
        if k == m:
            hits.append(i - m + 1)
            k = pi[k - 1]                   # allow overlaps
    return hits


assert prefix_function("ababaca") == [0, 0, 1, 2, 3, 0, 1]
assert kmp_search("abababcabab", "abab") == [0, 2, 7]
assert kmp_search("aaaa", "aa") == [0, 1, 2]
  • while shrinks k on a mismatch, if grows it on a match; both functions share this shape.
  • An empty pattern matches everywhere, as with str.find; without the check, pattern[0] fails.
  • i - m + 1 turns the match's end i into its start.

Python: a trie with autocomplete

class TrieNode:
    def __init__(self) -> None:
        self.children: dict[str, "TrieNode"] = {}
        self.is_end = False


class Trie:
    def __init__(self) -> None:
        self.root = TrieNode()

    def insert(self, word: str) -> None:
        node = self.root
        for ch in word:
            node = node.children.setdefault(ch, TrieNode())
        node.is_end = True

    def _walk(self, prefix: str) -> TrieNode | None:
        node = self.root
        for ch in prefix:
            node = node.children.get(ch)
            if node is None:
                return None
        return node

    def complete(self, prefix: str, limit: int = 10) -> list[str]:
        start = self._walk(prefix)
        if start is None:
            return []
        out: list[str] = []
        stack = [(start, prefix)]
        while stack and len(out) < limit:
            node, word = stack.pop()
            if node.is_end:
                out.append(word)
            for ch in sorted(node.children, reverse=True):
                stack.append((node.children[ch], word + ch))
        return out


t = Trie()
for w in ["car", "cart", "cat", "dog"]:
    t.insert(w)
assert t.complete("ca") == ["car", "cart", "cat"]
  • A dict of children works for any alphabet; for lowercase only, 26 slots are faster.
  • Without is_end, the bare prefix would be listed as a word.
この章について質問がありますか?
前の章How It Works次の章Complexity
ca
  • complete uses an explicit stack; children are pushed in reverse so they pop in sorted order.
  • C++

    #include <string>
    #include <vector>
    
    std::vector<int> prefixFunction(const std::string& p) {
        std::vector<int> pi(p.size(), 0);
        int k = 0;
        for (size_t i = 1; i < p.size(); ++i) {
            while (k > 0 && p[i] != p[k]) k = pi[k - 1];
            if (p[i] == p[k]) ++k;
            pi[i] = k;
        }
        return pi;
    }
    
    std::vector<int> kmpSearch(const std::string& text, const std::string& pattern) {
        std::vector<int> hits;
        const int m = static_cast<int>(pattern.size());
        if (m == 0) return hits;
        const std::vector<int> pi = prefixFunction(pattern);
        int k = 0;
        for (size_t i = 0; i < text.size(); ++i) {
            while (k > 0 && text[i] != pattern[k]) k = pi[k - 1];
            if (text[i] == pattern[k]) ++k;
            if (k == m) {
                hits.push_back(static_cast<int>(i) - m + 1);
                k = pi[k - 1];
            }
        }
        return hits;
    }

    std::string holds bytes, so UTF-8 positions are byte offsets. An empty pattern returns nothing here.

    Java

    import java.util.ArrayList;
    import java.util.List;
    
    public final class Kmp {
        static int[] prefixFunction(String p) {
            int[] pi = new int[p.length()];
            int k = 0;
            for (int i = 1; i < p.length(); i++) {
                while (k > 0 && p.charAt(i) != p.charAt(k)) k = pi[k - 1];
                if (p.charAt(i) == p.charAt(k)) k++;
                pi[i] = k;
            }
            return pi;
        }
    
        static List<Integer> search(String text, String pattern) {
            List<Integer> hits = new ArrayList<>();
            int m = pattern.length();
            if (m == 0) return hits;
            int[] pi = prefixFunction(pattern);
            int k = 0;
            for (int i = 0; i < text.length(); i++) {
                while (k > 0 && text.charAt(i) != pattern.charAt(k)) k = pi[k - 1];
                if (text.charAt(i) == pattern.charAt(k)) k++;
                if (k == m) {
                    hits.add(i - m + 1);
                    k = pi[k - 1];
                }
            }
            return hits;
        }
    }

    charAt returns UTF-16 code units: matching stays exact, but positions count code units.

    TypeScript

    export function prefixFunction(p: string): number[] {
      const pi = new Array<number>(p.length).fill(0);
      let k = 0;
      for (let i = 1; i < p.length; i++) {
        while (k > 0 && p[i] !== p[k]) k = pi[k - 1];
        if (p[i] === p[k]) k++;
        pi[i] = k;
      }
      return pi;
    }
    
    export function kmpSearch(text: string, pattern: string): number[] {
      const hits: number[] = [];
      const m = pattern.length;
      if (m === 0) return hits;
      const pi = prefixFunction(pattern);
      let k = 0;
      for (let i = 0; i < text.length; i++) {
        while (k > 0 && text[i] !== pattern[k]) k = pi[k - 1];
        if (text[i] === pattern[k]) k++;
        if (k === m) {
          hits.push(i - m + 1);
          k = pi[k - 1];
        }
      }
      return hits;
    }

    Summary

    • KMP: shrink k on a mismatch, grow it on a match.
    • A trie node holds children and an is_end flag; autocomplete collects words below the prefix node.
    • Positions are bytes in C++, UTF-16 units in Java and TypeScript, code points in Python.

    コメント 0件

    人気のコメント順新しい順

    ログイン · ログインするとコメントできます。