目录
Description
有一个很长的由小写字母组成字符串。为了便于对这个字符串进行分析,需要将它划分成若干个部分,每个部分称为一个单词。出于减少分析量的目的,我们希望划分出的单词数越少越好。你就是来完成这一划分工作的。
Format
Input
第 1 行,一个字符串。(字符串的长度不超过 100)
第 2 行一个整数 n,表示单词的个数。(n<=100)
第 3∼n+2 行,每行列出一个单词。
Output
一个整数,表示字符串可以被划分成的最少的单词数。
Samples
输入数据 1
realityour
5
real
reality
it
your
our
输出数据 1
2
Hint
原字符串可拆成real+it+your或reality+our,由于reality+our仅为两个部分,因此最优解为2,另外注意,单词列表中的每个单词都可以重复使用多次,也可以不用
Limitation
1s, 1024KiB for each test case.
题解:
就是变形的背包问题,经过复杂的判断和循环遍历后寻找最小的解决方案,状态转移方程:
dp[k]=min(dp[k],dp[k-a[j].size()]+1);//状态转移方程
程序:
#include<bits/stdc++.h>
using namespace std;
string a[110],s;
int n,len,len1,dp[110];
int main(){
cin>>s>>n;
len=s.size();//串的长度
for(int i=0;i<n;i++)
cin>>a[i];
memset(dp,0x3f,sizeof(dp));//设为无穷大
dp[0]=0;
for(int i=0,k;i<len;i++,k=i+1;/*遍历到的位置*/)
for(int j=0;j<n;j++len1=a[j].size();/*单词的长度*/)
if(len1<=k)//判断此单词的长度是否小于当前遍历的位置
if(s.substr(k-len1,len1)==a[j])//判断串的部分是否与当前遍历的单词相同
dp[k]=min(dp[k],dp[k-a[j].size()]+1);//状态转移方程
cout<<dp[len];
return 0;
}