codeforces 645E (贪心+dp)

对于求子串个数明显是用dp,对于每添加一个字符ch,必然是多2*dp[i-1]个串,那必然还有重复的串,就是之前ch出现位置的串,需要减去。
对于添加字母,贪心的加上之前出现位置最小的字母。

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <map>
#include <sstream>
#define LL long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-6
const int maxn = 1000000 + 5;
using namespace std;
char s[maxn];
int pre[26];
LL sum[maxn];
int idx(char ch){
    return ch - 'a';
}
LL dp[maxn];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    int len = (int)strlen(s+1);
    memset(pre, 0, sizeof(pre));
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for(int i=1; i<=len; i++){
        if(pre[idx(s[i])] == 0)
            dp[i] = (dp[i-1] * 2) % mod;
        else
            dp[i] = (2*dp[i-1] - dp[pre[idx(s[i])]-1] + mod) % mod;
        pre[idx(s[i])] = i;
    }
    for(int i=len+1; i<=len+n; i++){
        int id = 0, pos = i;
        for(int j=0; j<m; j++){
            if(pre[j] < pos){
                pos = pre[j];
                id = j;
            }
        }
        if(pre[id] == 0)
            dp[i] = (dp[i-1] * 2) % mod;
        else
            dp[i] = (2*dp[i-1] - dp[pos-1] + mod) % mod;
        pre[id] = i;
    }
    printf("%lld\n", dp[n+len] % mod);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值