[蓝桥杯 2025 国 Python A] 倒排索引

· · 题解

题意

在信息检索系统中,需要根据 N-Gram 分词算法实现文档与查询词的匹配:

生成规则分两种情况。

情况一(字符串长度小于 \min):

情况二(字符串长度大于等于 \min):

对每个文档生成所有合法 N-Gram,存入 \texttt{unordered\_set} 集合(去重且支持快速查询)。

对查询词生成所有合法 N-Gram,形成序列 P

遍历每个文档的 N-Gram 集合,判断 P 中是否存在至少一个 N-Gram 在集合中。若存在,则文档匹配成功。

代码

以下是 c++ 版的。

#include <bits/stdc++.h>
using namespace std;
int n,minl,maxl;
vector<string> gngrams(const string& s,int minl,int maxl){
    vector<string> ngrams;
    int len=s.size();
    if(len<minl){
        ngrams.push_back(s);
        return ngrams;
    }
    for(int l=minl;l<=maxl&&l<=len;l++){
        for(int i=0;i<=len-l;i++) ngrams.push_back(s.substr(i,l));
    }
    return ngrams;
}
int main(){
    cin>>n>>minl>>maxl;
    vector<unordered_set<string>> dngrams(n);
    for(int i=0;i<n;i++){
        string d;
        cin>>d;
        vector<string>ngrams=gngrams(d,minl,maxl);
        for(const string& ng:ngrams) dngrams[i].insert(ng);
    }
    string q;
    cin>>q;
    vector<string> qngrams=gngrams(q,minl,maxl);
    int cnt=0;
    for(int i=0;i<n;i++){
        for(const string& qng:qngrams){
            if(dngrams[i].count(qng)){
                cnt++;
                break; 
            }
        }
    }
    cout<<cnt;
    return 0;
}

代码 Python 版(AI 辅助生成)

作者其实把 Python 忘了。

def generate_ngrams(s, min_length, max_length):
    """生成字符串的 n-gram 列表"""
    ngrams = []
    length = len(s)

    # 当字符串长度小于最小 n-gram 长度时,直接返回原字符串
    if length < min_length:
        ngrams.append(s)
        return ngrams

    # 生成指定长度范围内的所有 n-gram
    for l in range(min_length, max_length + 1):
        if l > length:
            continue
        for i in range(length - l + 1):
            ngrams.append(s[i:i+l])

    return ngrams

def main():
    # 读取输入
    n, min_length, max_length = map(int, input().split())

    # 存储每个文档的 n-gram 集合
    document_ngrams = [set() for _ in range(n)]

    # 处理每个文档并生成 n-gram
    for i in range(n):
        document = input()
        ngrams = generate_ngrams(document, min_length, max_length)
        document_ngrams[i].update(ngrams)

    # 处理查询字符串
    query = input()
    query_ngrams = generate_ngrams(query, min_length, max_length)

    # 计算匹配的文档数量
    count = 0
    for i in range(n):
        # 只要查询的 n-gram 中有一个存在于文档的 n-gram 集合中,即计数
        for ng in query_ngrams:
            if ng in document_ngrams[i]:
                count += 1
                break  # 找到一个匹配就可以停止检查该文档

    # 输出结果
    print(count)

if __name__ == "__main__":
    main()