Alice is attempting to type a specific string on her computer. However, she tends to be clumsy and may press a key for too long, resulting in a character being typed multiple times.
You are given a string word, which represents the final output displayed on Alice’s screen. You are also given a positive integer k.
Return the total number of possible original strings that Alice might have intended to type, if she was trying to type a string of size at leastk.
Since the answer may be very large, return it modulo10^9 + 7.
We can group consecutive identical characters in word and, for each group, decide how many characters to keep (at least 1, up to the group length). The total length of the original string must be at least k. We use dynamic programming to count the number of ways to select how many characters to keep from each group so that the total length is at least k.
Group the string into consecutive runs of the same character, storing their lengths.
Let dp[i][l] be the number of ways to process the first i groups to get a string of length l.
Initialize dp[0][0] = 1 (no groups, length 0).
For each group, for each possible current length, try all possible numbers of characters to keep from the group (from 1 to group length), and update the DP.
classSolution:
defpossibleStringCount(self, word: str, k: int) -> int:
MOD =10**9+7 n = len(word)
groups = []
i =0while i < n:
j = i
while j < n and word[j] == word[i]:
j +=1 groups.append(j - i)
i = j
m = len(groups)
dp = [0] * (n +1)
dp[0] =1for g in groups:
ndp = [0] * (n +1)
for l in range(n +1):
if dp[l]:
for take in range(1, g +1):
if l + take <= n:
ndp[l + take] = (ndp[l + take] + dp[l]) % MOD
dp = ndp
return sum(dp[k:]) % MOD
classSolution {
public:int possibleStringCount(string word, int k) {
constint MOD =1e9+7;
int n = word.size();
vector<int> groups;
for (int i =0; i < n;) {
int j = i;
while (j < n && word[j] == word[i]) ++j;
groups.push_back(j - i);
i = j;
}
vector<int> dp(n +1);
dp[0] =1;
for (int g : groups) {
vector<int> ndp(n +1);
for (int l =0; l <= n; ++l) {
if (dp[l]) {
for (int take =1; take <= g; ++take) {
if (l + take <= n)
ndp[l + take] = (ndp[l + take] + dp[l]) % MOD;
}
}
}
dp = ndp;
}
int ans =0;
for (int l = k; l <= n; ++l) ans = (ans + dp[l]) % MOD;
return ans;
}
};
classSolution {
publicintpossibleStringCount(String word, int k) {
int MOD = 1_000_000_007;
int n = word.length();
List<Integer> groups =new ArrayList<>();
for (int i = 0; i < n;) {
int j = i;
while (j < n && word.charAt(j) == word.charAt(i)) ++j;
groups.add(j - i);
i = j;
}
int[] dp =newint[n + 1];
dp[0]= 1;
for (int g : groups) {
int[] ndp =newint[n + 1];
for (int l = 0; l <= n; ++l) {
if (dp[l]> 0) {
for (int take = 1; take <= g; ++take) {
if (l + take <= n)
ndp[l + take]= (ndp[l + take]+ dp[l]) % MOD;
}
}
}
dp = ndp;
}
int ans = 0;
for (int l = k; l <= n; ++l) ans = (ans + dp[l]) % MOD;
return ans;
}
}
classSolution {
funpossibleStringCount(word: String, k: Int): Int {
val MOD = 1_000_000_007
val n = word.length
val groups = mutableListOf<Int>()
var i = 0while (i < n) {
var j = i
while (j < n && word[j] == word[i]) j++ groups.add(j - i)
i = j
}
var dp = IntArray(n + 1)
dp[0] = 1for (g in groups) {
val ndp = IntArray(n + 1)
for (l in0..n) {
if (dp[l] > 0) {
for (take in1..g) {
if (l + take <= n)
ndp[l + take] = (ndp[l + take] + dp[l]) % MOD
}
}
}
dp = ndp
}
var ans = 0for (l in k..n) ans = (ans + dp[l]) % MOD
return ans
}
}
impl Solution {
pubfnpossible_string_count(word: String, k: i32) -> i32 {
constMOD: i32=1_000_000_007;
let n = word.len();
let bytes = word.as_bytes();
letmut groups =vec![];
letmut i =0;
while i < n {
letmut j = i;
while j < n && bytes[j] == bytes[i] { j +=1; }
groups.push(j - i);
i = j;
}
letmut dp =vec![0; n +1];
dp[0] =1;
for&g in&groups {
letmut ndp =vec![0; n +1];
for l in0..=n {
if dp[l] >0 {
for take in1..=g {
if l + take <= n {
ndp[l + take] = (ndp[l + take] + dp[l]) %MOD;
}
}
}
}
dp = ndp;
}
letmut ans =0;
for l in k asusize..=n {
ans = (ans + dp[l]) %MOD;
}
ans
}
}