CF_176B Word Cut

本文解析了 CodeForces 上 B.WordCut 问题,该问题是关于字符串操作与动态规划的经典题目。文章详细介绍了如何通过旋转字符串来解决特定条件下字符串匹配的问题,并提供了一个高效的 C++ 实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B. Word Cut

http://codeforces.com/contest/176/problem/B

题意:
给定a串和b串,要求切k次,每次切完将尾部分放在头的前面(a = xy -> yx ,x、y为a的子串),问有多少种方案使得切k次后a串变为b串。[模:1000000007 (109 + 7)]
数据:
 (0 ≤ k ≤ 105) (la,lb≤1000 )

思路:

 1. 可以把串看做一个环,那么每次切的操作则相当于只是旋转了串。
 2. 那么相当于a环每次必须旋转,求k次后有多少种方案变成b环。
 3. 那么 DP 或者 直接算 。
 4. DP每次只有两类变化:
    (l-1)种从 a串 变成 其它串;
    (l-2)种从 其它串 变成 其它串 + 1种从 a串 变成 其它串;
     即:
        dp[i%2][0]=(l-1)*dp[(i+1)%2][1];
        dp[i%2][1]=(l-2)*dp[(i+1)%2][1] + dp[(i+1)%2][0] ;
5. 最后累加 b串 所有循环后满足的情况。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 2007;
const int M = 100005;
const int INF = 100000001;
const int MOD = 1000000007;
int n,m;
char s[N],t[N];
char tmp[N];
LL dp[3][3];
int k;
int sa[N];
int main()
{
    while (~scanf("%s%s",&s,&t))
    {
        scanf("%d",&k);
        int l=strlen(s);
        int pos=0;
        for (int i=0;i<l;i++)
        {
            memset(tmp,0,sizeof(tmp));
            for (int j=0;j<l;j++)
                tmp[j]=t[(i+j)%l];
            if (strcmp(s,tmp)==0)
                sa[pos++]=i;
        }
        if (pos==0)
        {
            printf("0\n");
            continue;
        }
        if (k==0)
        {
            if (sa[0]==0)
                printf("1\n");
            else
                printf("0\n");
            continue;
        }
        memset(dp,0,sizeof(dp));
        dp[1][0]=0;
        dp[1][1]=1;
        for (int i=2;i<=k;i++)
        {
            dp[i%2][0]=((l-1)*dp[(i+1)%2][1] + MOD)%MOD;
            dp[i%2][1]=(dp[(i+1)%2][0]+(l-2)*dp[(i+1)%2][1] + MOD)%MOD;
        }
        LL ans=0;
        for (int i=0;i<pos;i++)
            ans=(ans+dp[(k)%2][sa[i]==0?0:1])%MOD;
        printf("%d\n",ans);
    }  
    return 0;
}
/*
ab
ab
2

ababab
ababab
1

ab
ba
2
*/

珈百璃

``` from bertopic import BERTopic import numpy as np import pandas as pd from umap import UMAP from hdbscan import HDBSCAN from sklearn.feature_extraction.text import CountVectorizer from bertopic.vectorizers import ClassTfidfTransformer import re import nltk from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS from nltk.tokenize import word_tokenize from wordcloud import WordCloud import matplotlib.pyplot as plt # 加载原始文本数据(仍需用于主题表示) df = pd.read_csv('tokenized_abstract.csv', encoding='utf-8') sentences = df['Tokenized_Abstract'].tolist() print('文本条数: ', len(sentences)) print('预览第一条: ', sentences[0]) # 检查缺失值 print("缺失值数量:", df['Tokenized_Abstract'].isna().sum()) # 检查非字符串类型 non_str_mask = df['Tokenized_Abstract'].apply(lambda x: not isinstance(x, str)) print("非字符串样本:\n", df[non_str_mask]['Tokenized_Abstract'].head()) vectorizer_model = None from sentence_transformers import SentenceTransformer # 加载时间数据 df['Date'] = pd.to_datetime(df['Date']) # 从Date列提取年份 years = df['Date'].dt.year print(years) # Step 1 - Extract embeddings embedding_model = SentenceTransformer("C:\\Users\\18267\\.cache\\huggingface\\hub\\models--sentence-transformers--all-mpnet-base-v2\\snapshots\\9a3225965996d404b775526de6dbfe85d3368642") embeddings = np.load('clean_emb_last.npy') print(f"嵌入的形状: {embeddings.shape}") # Step 2 - Reduce dimensionality umap_model = UMAP(n_neighbors=7, n_components=10, min_dist=0.0, metric='cosine',random_state=42) # Step 3 - Cluster reduced embeddings hdbscan_model = HDBSCAN(min_samples=7, min_cluster_size=60,metric='euclidean', cluster_selection_method='eom', prediction_data=True) # Step 4 - Tokenize topics # Combine custom stop words with scikit-learn's English stop words custom_stop_words = ['h2', 'storing', 'storage', 'include', 'comprise', 'utility', 'model', 'disclosed', 'embodiment', 'invention', 'prior', 'art', 'according', 'present', 'method', 'system', 'device', 'may', 'also', 'use', 'used', 'provide', 'wherein', 'configured', 'predetermined', 'plurality', 'comprising', 'consists', 'following', 'characterized', 'claim', 'claims', 'said', 'first', 'second', 'third', 'fourth', 'fifth', 'one', 'two', 'three','hydrogen'] # Create combined stop words set all_stop_words = set(custom_stop_words).union(ENGLISH_STOP_WORDS) vectorizer_model = CountVectorizer(stop_words=list(all_stop_words)) # Step 5 - Create topic representation ctfidf_model = ClassTfidfTransformer() # All steps together topic_model = BERTopic( embedding_model=embedding_model, # Step 1 - Extract embeddings umap_model=umap_model, # Step 2 - Reduce dimensionality hdbscan_model=hdbscan_model, # Step 3 - Cluster reduced embeddings vectorizer_model=vectorizer_model, # Step 4 - Tokenize topics ctfidf_model=ctfidf_model, # Step 5 - Extract topic words top_n_words=50 ) # 拟合模型 topics, probs = topic_model.fit_transform(documents=sentences, # 仍需提供文档用于主题词生成 embeddings=embeddings # 注入预计算嵌入) ) # 获取主题聚类信息 topic_info = topic_model.get_topic_info() print(topic_info)```基于已上传代码,使用BERTopic的动态主题功能,传入时间戳参数,并在拟合后分析主题随时间的变化,设置时间戳 t1=2000-2010 年,t2=2011-2018 年,t3=2019-2024 年。注意,嵌入、降维、聚类等步骤与先前保持一致,仅在主题表示步骤对 c-TF-IDF 算法进行调整,C-TF-IDF算法调整为: $ c-TF-IDF_{w,c,r} = \frac{\left(\sqrt{\frac{f_{w,c,r}}{f_c}} + \sqrt{\frac{f_{w,c,r-1}}{f_c}}\right) \cdot \log\left(1 + \frac{M - cf_w + 0.5}{cf_w + 0.5}\right)}{2} $ 公式文字说明: “其中,( f_{w,c,r} ) 为第 ( r ) 阶段时,词 ( w ) 在聚类簇 ( c ) 中出现的频次,( f_c ) 表示聚类簇 ( c ) 中词数。( M ) 表示簇的平均单词数,( cf_w ) 表示词 ( w ) 在所有簇中出现频次。” 最终分别选取每个主题在每个阶段改进 c-TF-IDF 值排名前 15 的单词作为关键词绘制演化图分析主题在不同阶段的动态变化。请你给出代码实现上述操作。
03-16
假如我用bertopic对英文专利摘要文本进行了静态主题表示,在此基础上现在我需要用bertopic自带的topic_over_time动态主题建模结合调整c-TF-IDF 算法进行动态主题表示,动态主题表示设置时间戳 t1=2000-2010 年,t2=2011-2018 年,t3=2019-2024 年。最终,将当前阶段和前一阶段的 c-TF-IDF 平均值作为当前阶段的权重分数,取权重分数前 15 的单词作为动态主题的关键词,形成动态主题词列表。注意,已经进行切词、去除停用词、标点符号的英文专利摘要文本保存在'tokenized_abstract.csv'中的'Tokenized_Abstract'字段内,并且在静态主题建模时已经进行了加载,专利摘要对应的时间数据保存在中'tokenized_abstract.csv'中的'Date'字段内,尚未加载,已经执行的静态主题模型的参数设置如下:from sentence_transformers import SentenceTransformer Step 1 - Extract embeddings embedding_model = SentenceTransformer(“C:\Users\18267\.cache\huggingface\hub\models–sentence-transformers–all-mpnet-base-v2\snapshots\9a3225965996d404b775526de6dbfe85d3368642”) embeddings = np.load(‘clean_emb_last.npy’) print(f"嵌入的形状: {embeddings.shape}") Step 2 - Reduce dimensionality umap_model = UMAP(n_neighbors=7, n_components=10, min_dist=0.0, metric=‘cosine’,random_state=42) Step 3 - Cluster reduced embeddings hdbscan_model = HDBSCAN(min_samples=7, min_cluster_size=60,metric=‘euclidean’, cluster_selection_method=‘eom’, prediction_data=True) Step 4 - Tokenize topics Combine custom stop words with scikit-learn’s English stop words custom_stop_words = [‘h2’, ‘storing’, ‘storage’, ‘include’, ‘comprise’, ‘utility’, ‘model’, ‘disclosed’, ‘embodiment’, ‘invention’, ‘prior’, ‘art’, ‘according’, ‘present’, ‘method’, ‘system’, ‘device’, ‘may’, ‘also’, ‘use’, ‘used’, ‘provide’, ‘wherein’, ‘configured’, ‘predetermined’, ‘plurality’, ‘comprising’, ‘consists’, ‘following’, ‘characterized’, ‘claim’, ‘claims’, ‘said’, ‘first’, ‘second’, ‘third’, ‘fourth’, ‘fifth’, ‘one’, ‘two’, ‘three’,‘hydrogen’] Create combined stop words set all_stop_words = set(custom_stop_words).union(ENGLISH_STOP_WORDS) vectorizer_model = CountVectorizer(stop_words=list(all_stop_words)) Step 5 - Create topic representation ctfidf_model = ClassTfidfTransformer() All steps together topic_model = BERTopic( embedding_model=embedding_model, # Step 1 - Extract embeddings umap_model=umap_model, # Step 2 - Reduce dimensionality hdbscan_model=hdbscan_model, # Step 3 - Cluster reduced embeddings vectorizer_model=vectorizer_model, # Step 4 - Tokenize topics ctfidf_model=ctfidf_model, # Step 5 - Extract topic words top_n_words=50 ) 现在,请你给出实现这一操作的python代码帮我完成静态主题表示之后的动态主题表示。调整后的c-TF-IDF计算公式如下: $ c-TF-IDF_{w,c,r} = \frac{\left(\sqrt{\frac{f_{w,c,r}}{f_c}} + \sqrt{\frac{f_{w,c,r-1}}{f_c}}\right) \cdot \log\left(1 + \frac{M - cf_w + 0.5}{cf_w + 0.5}\right)}{2} $ 文字说明: “其中,( f_{w,c,r} ) 为第 ( r ) 阶段时,词 ( w ) 在聚类簇 ( c ) 中出现的频次,( f_c ) 表示聚类簇 ( c ) 中词数。( M ) 表示簇的平均单词数,( cf_w ) 表示词 ( w ) 在所有簇中出现频次。”
03-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值