【NOIP2001提高组T3】统计单词个数-字符串上的动态规划

本文介绍了一种解决字符串分割问题的方法,目标是在给定的字符串和词典条件下,找到最佳的分割方式,使得每个分割部分包含尽可能多的词典中的单词。通过预计算区间内的单词数量,并使用动态规划进行状态转移,最终输出最大单词数。

(本人本题完成于2016-7-19)

题目大意:给定一个字符串(长度为20*p,不超过200)和一个包含一些单词(个数为n,1≤n≤6)的词典,问如何将该字符串分成K(不超过40)份,使得每份中包含的单词个数之和最大,输出这个最大值。以一个位置为起始点只能统计一个单词。

做法:用a[i][j]表示区间(i,j)内所含的单词个数,可以用暴力计算出所有a[i][j]。再设f[i][j]为字符串前i个字符分割成j份的最优解,最终答案即是f[20*p][K]。状态转移方程为:f[i][j]=max(f[i][j],f[k][j-1]+a[k+1][i])。

以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
long p,K,n,a[210][210]={0},f[210][210]={0}; //a,f的意义如上文所示
char w[10][210],s[210]; //w存储词典,s存储待处理的字符串
bool v[210]={0}; //v[i]表示当前以i为起始位置有没有统计过单词,值为1时代表已统计过

int main()
{
  scanf("%ld %ld\n",&p,&K);
  for(int i=1;i<=p;i++)
  {
    for(int j=(i-1)*20+1;j<=i*20;j++)
	  scanf("%c",&s[j]);
    scanf("\n");
  }
  scanf("%ld\n",&n);
  for(int i=1;i<=n;i++)
  {
    scanf("%s\n",w[i]);
    for(int j=1;j<i;j++)
	  if (!strcmp(w[i],w[j])) {i--;n--;break;} //比较,如果当前单词与已输入单词重复则舍去当前单词
  }
  
  for(int i=1;i<=20*p;i++)
    for(int j=i;j<=20*p;j++)
	{
	  memset(v,0,sizeof(v));
	  for(int k=1;k<=n;k++)
	  {
	    long len=strlen(w[k]);
		for(int ii=i;ii<=j-len+1;ii++)
		{
		  if (v[ii]) continue;
		  bool flag=1;
		  for(int jj=0;jj<len;jj++)
		    if (s[ii+jj]!=w[k][jj]) {flag=0;break;}
		  if (flag) {a[i][j]++;v[ii]=1;}
	    }
	  }
	} //暴力求出所有a[i][j]
  
  for(int k=1;k<=K;k++)
    for(int i=1;i<=20*p;i++)
	  for(int j=k-1;j<=i-1;j++) //注意从k-1开始,勿漏情况
	    f[i][k]=max(f[i][k],f[j][k-1]+a[j+1][i]);
  
  printf("%ld",f[20*p][K]);
  
  return 0;
}

### Python 实现统计单词个数 要实现统计单词个数的功能,可以通过读取文本文件并逐行处理内容来完成。以下是基于引用的内容以及扩展的知识所提供的解决方案。 #### 解决方案描述 为了满足题目需求,程序需具备以下功能: 1. **读取输入数据**:从标准输入或指定文件中获取待分析的文本。 2. **预处理文本**:将文本转换为统一的小写形式,并去除多余的空白符以便于后续操作[^1]。 3. **分割单词**:通过空格或其他分隔符分离出单个单词。 4. **统计单词频率**:利用 `collections.Counter` 或字典结构记录每个单词出现的次数。 5. **输出结果**:按照要求格式化输出单词及其对应频次。 下面是一个完整的 Python 代码示例: ```python import re from collections import Counter def count_words(text, target_word=None): # 将所有字母转为小写以忽略大小写的差异 text = text.lower() # 使用正则表达式提取单词,过滤掉非字母字符 words = re.findall(r&#39;\b\w+\b&#39;, text) # 如果目标单词为空,则计算整个文档的词频分布 word_counts = Counter(words) if target_word is None: result = dict(word_counts.most_common()) else: # 转为目标单词的小写版本用于比较 target_word = target_word.lower() result = {target_word: word_counts[target_word]} return result if __name__ == "__main__": input_text = """ This is a sample text with several words. The task involves counting the occurrences of each distinct word, ignoring case and punctuation marks such as commas or periods. """ # 假设用户希望查询某个特定单词 specific_word = "word" output = count_words(input_text, specific_word) print(f"Word &#39;{specific_word}&#39; appears {output[specific_word]} times.") # 查询整体词频分布 all_word_frequencies = count_words(input_text) print("Overall Word Frequencies:") for word, freq in all_word_frequencies.items(): print(f"{word}: {freq}") ``` 上述代码实现了两个主要功能:一是单独统计某一个单词在文本中的出现次数;二是返回整个文本中各单词的频率表[^2]。 #### 关键技术点解析 - **字符串标准化**:通过 `.lower()` 方法使大写字母变为小写,从而简化匹配逻辑。 - **正则表达式应用**:借助 `re.findall(&#39;\b\w+\b&#39;)` 提取出合法的英语单词序列[^3]。 - **高效计数工具**:采用 `Counter` 类型自动汇总重复项的数量,减少手动维护哈希表的工作量[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值