# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)
        self.sequence: str = sequence.upper().replace("U", "T")
        if not self.sequence:
            raise ValueError("Adapter sequence is empty")
        if max_errors >= 1 and self.sequence.count("N") != len(self.sequence):
            max_errors /= len(self.sequence) - self.sequence.count("N")
        self.max_error_rate: float = max_errors
        self.min_overlap: int = min(min_overlap, len(self.sequence))
        iupac = frozenset("ABCDGHKMNRSTUVWXY")
        if adapter_wildcards and not set(self.sequence) <= iupac:
            for c in self.sequence:
                if c not in iupac:
                    if c == "I":
                        extra = (
                            "For inosine, consider using N instead and please comment "
                            "on <https://github.com/marcelm/cutadapt/issues/546>."
                        )
                    else:
                        extra = "Use only characters 'ABCDGHKMNRSTUVWXY'."
                    raise InvalidCharacter(
                        f"Character '{c}' in adapter sequence '{self.sequence}' is "
                        f"not a valid IUPAC code. {extra}"
                    )
        # Optimization: Use non-wildcard matching if only ACGT is used
        self.adapter_wildcards: bool = adapter_wildcards and not set(
            self.sequence
        ) <= set("ACGT")
        self.read_wildcards: bool = read_wildcards
        self.indels: bool = indels
        self.aligner = self._aligner()


# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


# Path: src/cutadapt/adapters.py
import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)

        self.sequence: str = sequence.upper().replace("U", "T")
        if not self.sequence:
            raise ValueError("Adapter sequence is empty")
        if max_errors >= 1 and self.sequence.count("N") != len(self.sequence):
            max_errors /= len(self.sequence) - self.sequence.count("N")
        self.max_error_rate: float = max_errors
        self.min_overlap: int = min(min_overlap, len(self.sequence))
        iupac = frozenset("ABCDGHKMNRSTUVWXY")
        if adapter_wildcards and not set(self.sequence) <= iupac:
            for c in self.sequence:
                if c not in iupac:
                    if c == "I":
                        extra = (
                            "For inosine, consider using N instead and please comment "
                            "on <https://github.com/marcelm/cutadapt/issues/546>."
                        )
                    else:
                        extra = "Use only characters 'ABCDGHKMNRSTUVWXY'."
                    raise InvalidCharacter(
                        f"Character '{c}' in adapter sequence '{self.sequence}' is "
                        f"not a valid IUPAC code. {extra}"
                    )
        # Optimization: Use non-wildcard matching if only ACGT is used
        self.adapter_wildcards: bool = adapter_wildcards and not set(
            self.sequence
        ) <= set("ACGT")
        self.read_wildcards: bool = read_wildcards
        self.indels: bool = indels
        self.aligner = self._aligner()


    def _make_aligner(self, flags: int) -> Aligner: