【codevs1779】 单词的划分 解题报告

单词的划分  codevs1779黄金Gold

题目描述 Description

Problem有一个很长的由小写字母组成字符串。为了便于对这个字符串进行分析,需要将它划分成若干个部分,每个部分称为一个单词。出于减少分析量的目的,我们希望划分出的单词数越少越好。Output一个整数,表示字符串可以被划分成的最少的单词数。

  • 应该加上一个前提题目中提供的字符串肯定能被划分,否则输出增加判断语句。
输入描述 Input Description

 从文本文件word.in中读入数据。第一行,一个字符串。(字符串的长度不超过100),第二行一个整数n,表示单词的个数。(n<=100),第3~n+2行,每行列出一个单词。

输出描述 Output Description

 一个整数,表示字符串可以被划分成的最少的单词数。

样例输入 Sample Input

realityour
5
real
reality
it
your
our

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

(原字符串可拆成real+it+your或reality+our,由于reality+our仅为两个部分,因此最优解为2,另外注意,单词列表中的每个单词都可以重复使用多次,也可以不用)

【解题思路:dp】

f[i]表示这个字符串的前i个字母最少可以划分成多少个单词;

那么第一层循环以下strlen(s),指针也就是字符串中从头到尾每一个字母;

第二层循环枚举每一个单词,然后比较以下当前扫到的字符串的结尾是不是那个单词,如果是的话,那么f[i]=max(f[i],f[i-strlen(a[j])]+1);

很好理解。。

【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[200],word[105][200];
int s1,i,j,n;
int l[105],f[105];

int ok(int x,int y)//逐位比较
{
	int r;
	for (r=0;r<l[y];++r)
	  if (s[x+r]!=word[y][r])
	    return 0;
	return 1;
}

int main()
{
	cin>>s;
	s1=strlen(s);
	scanf("%d\n",&n);
	for (i=1;i<=n;++i)
	{
		cin>>word[i];
		l[i]=strlen(word[i]);//求出每一个单词的长度
	}
	memset(f,127/3,sizeof(f));
	f[0]=0;
	for (i=0;i<s1;++i)
	  for (j=1;j<=n;++j)
		if (i+1>=l[j])//字符串读进来的时候首位下标是0,所以i需要+1
		  if (ok(i-l[j]+1,j))
		    f[i+1]=min(f[i+1],f[i-l[j]+1]+1);
	printf("%d",f[s1]);
	return 0;
}
【我是迫不得已采用的cin,codevs上不知道为什么不识别gets】

你可能感兴趣的:(dp)