17chd校赛E题 Colorful Ribbon(dp)

来源:互联网 发布:会员卡读卡数据 编辑:程序博客网 时间:2024/06/08 17:08

题目链接:http://112.74.33.53/contest/5/problem/36/

Colorful Ribbon

发布时间: 2017年4月19日 15:15   最后更新: 2017年4月19日 15:35   时间限制: 1000ms   内存限制: 128M

    Lizishu has a colorful ribbon, which can be expressed as a string consists of only lowercase letters, and each letter represents a color.

    Now she wants to divide the ribbon into several parts so that no color appears more than one time in each part.

    Tell her how many different ways can she divide the ribbon, output the answer modulo109+7.

The first line contains an integer number T, the number of test cases.

i-th of each next T lines contains a string s consists of lowercase letters (1|s|105).

For each test case print the answer modulo 109+7.

复制
2aabcba
112


学校校赛的一道题,,反正当时是不会做的
题意:给定一个字符串 把他切割成很多部分 使每一部分中都没有重复的字母出现 问有多少种方法 注意样例1中a有一种
思路:居然是一道dp。。。
          对于串中的当前字母x 如果他的前一个字母和他不相等 那么他至少可以有和前一个字母一样的切割方法
          于是一直往前递推 直到出现一个字母与到x的这一段字母中出现重复的 即为不合法 记这个为起点p
          那么x字母的切割方法即为把前面中的合法字母切割方法加起来   转移方程见代码
          例如 abcba

 abcbadp[0]=1dp[1]=1dp[2]=2dp[3]=4dp[4]=6dp[5]=12 pre[1]=1pre[2]=2pre[3]=3pre[2]=4pre[1]=5
          第二个b的答案为第一个b加到第二个b 第二个a的答案为第一个b加到第二个a
          于是 找到这个起点p就需要一个前缀数组来记录当前字母上一次出现的大小 例如abcba 最后一个a上一次出现是在0 但是他的合法部分在第一个b 所以找p应该有一个              p=max(p,pre[s[i]-'a'+1])的操作

#include<stdio.h>#include<algorithm>#include<string>#include<iostream>#include<string.h>using namespace std;long long int dp[100005];int pre[30];   int main(){int T;scanf("%d",&T);while(T--){string s;cin>>s;int len=s.size();memset(dp,0,sizeof(dp));memset(pre,0,sizeof(pre));int i,j;dp[0]=1;int p=0;for(i=0;i<len;i++){int temp=pre[s[i]-'a'+1];p=max(p,temp);for(j=p;j<i+1;j++){dp[i+1]+=(dp[j]%1000000007); //注意这两行不能写反 我就在这wa了一发。。 dp[i+1]%=1000000007;}pre[s[i]-'a'+1]=i+1;}printf("%lld\n",dp[len]);}return 0;}


0 0