Language Learning - ieeextreme15

题目大意

给N(<=10^5)个字符串{str[1],str[2],...,str[N]},常数K(<N)。用这些字符串造出不同的句子(str[a1] str[a2] ... str[ax] ...)要求相邻两个字符串的下标的绝对值大于K 且 下标递增。问能造出多少个不同的句子
动态规划的想法:
用dp[i]表示以字符串str[i]结尾,且和i前面的句子不同的句子的数量
则结果表示为ans=dp[1]+dp[2]+...+dp[N]

状态转移:

A.如果str[i]还未出现在{1到i-1}中,则dp[i]=1+sum(dp[1],dp[2],...,dp[i-K-1])
B.如果str[i]上一次出现在j,dp[i]=sum(dp[j-K],...,dp[i-K-1])

贴代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod = 1e9 + 7, N = 2e5 + 5;

ll sum[N];
int main()
{
    int T, n, k;
    scanf("%d", &T);
    while (T--)
    {
        char str[12];
        sum[0] = 0;
        map<string, int> latest;
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; i++)
        {
            scanf("%s", str);
            int ik1 = max(0, i - k - 1);
            ll dp_i = sum[ik1];
            if (latest.find(str) == latest.end())
                dp_i++;
            else
                dp_i -= sum[latest[str]];
            dp_i = (dp_i + mod) % mod;
            sum[i] = (sum[i - 1] + dp_i) % mod;
            latest[str] = ik1;
        }
        printf("%lld\n", sum[n]);
    }
    return 0;
}
posted @ 2021-10-28 22:11  早点跑路远离折磨  阅读(67)  评论(0)    收藏  举报