After getting kicked out of her reporting job for not knowing the alphabet, Bessie has decided to attend school at the Fillet and Eggs Eater Academy. She has been making good progress with her studies and now knows the first k English letters.
Each morning, Bessie travels to school along a sidewalk consisting of m + n tiles. In order to help Bessie review, Mr. Moozing has labeled each of the first m sidewalk tiles with one of the first k lowercase English letters, spelling out a string t. Mr. Moozing, impressed by Bessie's extensive knowledge of farm animals, plans to let her finish labeling the last n tiles of the sidewalk by herself.
Consider the resulting string s (|s| = m + n) consisting of letters labeled on tiles in order from home to school. For any sequence of indices p1 < p2 < ... < pq we can define subsequence of the string s as string sp1sp2... spq. Two subsequences are considered to be distinct if they differ as strings. Bessie wants to label the remaining part of the sidewalk such that the number of distinct subsequencesof tiles is maximum possible. However, since Bessie hasn't even finished learning the alphabet, she needs your help!
Note that empty subsequence also counts.
The first line of the input contains two integers n and k (0 ≤ n ≤ 1 000 000, 1 ≤ k ≤ 26).
The second line contains a string t (|t| = m, 1 ≤ m ≤ 1 000 000) consisting of only first k lowercase English letters.
Determine the maximum number of distinct subsequences Bessie can form after labeling the last n sidewalk tiles each with one of the first k lowercase English letters. Since this number can be rather large, you should print it modulo 109 + 7.
Please note, that you are not asked to maximize the remainder modulo 109 + 7! The goal is to maximize the initial value and then print the remainder.
1 3 ac
8
0 2 aaba
10
In the first sample, the optimal labeling gives 8 different subsequences: "" (the empty string), "a", "c", "b", "ac", "ab", "cb", and "acb".
In the second sample, the entire sidewalk is already labeled. The are 10 possible different subsequences: "" (the empty string), "a", "b", "aa", "ab", "ba", "aaa", "aab", "aba", and "aaba". Note that some strings, including "aa", can be obtained with multiple sequences of tiles, but are only counted once.
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; } const int N = 1e6+10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f; int m, n, k; char s[N]; int f[N+N]; //f[i]表示尾端点在[i]条件下的本质不同子串个数 int sum[N+N]; //sum[i]表示尾端点在[1,i]条件下的本质不同子串个数 int pre[128]; //pre[ch]表示字符同为ch的前一个字符的下标 int main() { while (~scanf("%d%d", &n,&k)) { MS(pre, -1); scanf("%s", s + 1); m = strlen(s + 1); sum[0] = 1; for (int i = 1; i <= m + n; ++i) { char ch; if (i <= m)ch = s[i]; else { ch = 'a'; for (char i = 'a' + 1; i < 'a' + k; ++i)if (pre[i] < pre[ch])ch = i; } //如果字符s[i]是第一次出现,那么以它为结尾,可以累加上之前所有本质不同子串 if (pre[ch] == -1)f[i] = sum[i - 1]; //如果字符s[i]不是第一次出现,那么以它为结尾,只可以累加上[pre[i],i-1]范围内的所有本质不同子串 else f[i] = (sum[i - 1] - sum[pre[ch]-1] + Z) % Z; sum[i] = (sum[i - 1] + f[i]) % Z; pre[ch] = i; } printf("%d\n", sum[m + n]); } return 0; } /* 【trick&&吐槽】 很多题目不要总想着是自己不会的算法。 尝试用自己会的知识解决题目才是一个ACMer要具备的素质 【题意】 给你一个长度为m(1e5)的字符串。 我们还可以在这个字符串后面添加长度为n(1e5)的串,添加串的字符集为[1,26] 问你最后最多能使得这个字符串中有多少个本质不同的子串。 输出子串个数%(1e9+7) 【类型】 DP 【分析】 首先,对于前m位。 如何算本质不同字符串的个数呢? 如果字符s[i]是第一次出现,那么以它为结尾,可以累加上之前所有本质不同子串 如果字符s[i]不是第一次出现,那么以它为结尾,只可以累加上[pre[i],i-1]范围内新出现的所有本质不同子串 然而,接下来需要处理,后面要添加什么字符。 我们分析DP转移方程,发现每次加的是一个区间范围内的本质不同子串。 所以我们只要使得这个字符上一次出现的位置距离本次出现的位置尽可能远就可以啦。 【时间复杂度&&优化】 O(m+nk) */