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;
}