P1026 [NOIP2001 提高组] 统计单词个数-字符串处理与DP

[NOIP2001 提高组] 统计单词个数 - 洛谷

难点在于一个字母不能再用,this

在不划分时,若单词为 this th his is

1-4有this(th),his,is也就是三个,可以倒着推 4有0个,34有1个,234有2个,1234有三个,也就是倒着推推到一个新位置时,只要这个位置包含了一个新的字符串,那么数量加一即可,且只能加1,用了一个就不能用,这样我们就处理出来了,i--j字符串的个数,且互不影响,相互独立;

所谓倒着推,就是说,dp[i][j] 由dp[i-1][j]推来,固定了j,i向前遍历即可

for(int j=len;j>=1;j--)
 for(int i=j;i>=1;i--)
  

j不一定倒序枚举,正枚举已然可以枚举出全部情况,正如i++,j++能够枚举出全部"[i][j]" (i<=j)的情况一样。

然后设置dp[i][j]为前i个划分成j段的最大个数,承接时,枚举承接点。注意应该先枚举划分段数,因为需要之前阶段划分段数转移而来。

# include
#include
#include
# include
# include
using namespace std;
int p,K,n;
string s,t;
string  c[10];
int sum[210][210];
int dp[210][50];
bool fun(int l,int r)
{
   string  s1=s.substr(l,r-l+1);

   for(int i=1;i<=n;i++)
    {

        if(s1.find(c[i])==0)
        {
            return 1;
        }

    }
    return 0;
}
int main ()
{
   cin>>p>>K;
   s+='0';
   for(int i=1;i<=p;i++)
   {
       cin>>t;
       s+=t;
   }

   int len=s.length()-1;

   //cout<>n;
   for(int i=1;i<=n;i++)
   {
       cin>>c[i];
   }
   int j;
   //int i;
   for(int i=1;i<=len;i++)
    for(int j=i;j>=1;j--){//预处理出sum[i][j]
        sum[j][i]=sum[j+1][i];
        if(fun(j,i))sum[j][i]++;
    }

 for(int k=1; k<=K; k++)
    {
        for(int i=1; i<=len; i++)
         {
            for(int j=k-1; j

你可能感兴趣的:(动态规划,NOIP)