首页 > 其他分享 >tomorin的字符串迷茫值

tomorin的字符串迷茫值

时间:2024-02-25 15:55:05浏览次数:17  
标签:子串 删除 int 迷茫 tomorin 字符串 mygo

tomorin的字符串迷茫值

题目描述

tomorin定义一个字符串的迷茫值为该字符串包含"mygo"连续子串的个数。例如"mygomygo"、"itsmygo"的迷茫值分别为 2,1,而"bangdream"的迷茫值为 0。

现在tomorin有一个字符串,她准备删除一些字符,但不能删除两个连续字符。

tomorin想知道在所有删除方案中,字符串的迷茫值之和是多少?

由于答案可能很大,你需要将答案对 $10^9+7$ 取模。

输入描述:

一个仅包含小写字母的字符串,长度不超过 $2 \times 10^5$。

输出描述:

一个整数,代表迷茫值之和。由于答案可能很大,你只需要输出答案对 $10^9+7$ 取模的结果。

示例1

输入

mygogo

输出

3

说明

方案 1:什么都不删,"mygogo",迷茫值为 1。

方案 2:删除第 5 个字符,"mygoo",迷茫值为 1。

方案 3:删除第 6 个字符,"mygog",迷茫值为 1。

因此答案为 3。

 

解题思路

  感觉是用贡献法的一类题。只要遇到统计某些量的题目时,可以考虑答案是由哪些情况做出贡献的,然后再去枚举这些情况分别统计。

  显然在这题中只有在删除后是 "mygo" 的子串才会对答案有贡献,那么就可以按照左端点将子串进行分类,枚举看看以 $i$ 为左端点的子串有多少种删除操作变成 "mygo"。由于在删除操作中不能删除两个相邻的字符,因此如果两个字符的距离超过 $2$,那么这两个字符间的字符不可能被删完。因此如果要获得 "mygo",那么只有这 $2^3 = 8$ 种子串可以得到:"mygo","m_ygo","my_go","myg_o","m_y_go","m_yg_o","my_g_o","m_y_g_o"。其中 "_" 指任意一个字符。

  只需依次枚举这 $8$ 种子串,看看是否匹配以 $i$ 为左端点的子串。子串内的删除方法是固定的,子串的两边即 $[1,i-1]$ 和 $[i+m,n]$($m$ 指 $8$ 种子串的长度)的方法是任意的,可以用动态规划来预处理。

  定义 $f(i,0)$ 表示区间 $[1,i]$ 中不删除第 $i$ 个字符的所有删除方法的数量。同理 $f(i,1)$ 表示区间 $[1,i]$ 中删除第 $i$ 个字符的所有删除方法的数量。状态转移方程就是 $f(i,0) = f(i-1,0) + f(i-1,1)$,$f(i,1) = f(i-1,0)$。那么区间 $[1,i]$ 的所有删除方案就是 $f(i,0)+f(i,1)$。同理定义 $g(i,0)$ 表示区间 $[i,n]$ 中不删除第 $i$ 个字符的所有删除方法的数量,$g(i,1)$ 表示区间 $[i,n]$ 中删除第 $i$ 个字符的所有删除方法的数量。状态转移方程就是 $g(i,0) = g(i+1,0) + g(i+1,1)$,$g(i,1) = g(i+1,0)$。那么区间 $[i,n]$ 的所有删除方案就是 $g(i,0)+g(i,1)$。

  因此以 $i$ 为左端点的子串如果匹配这 $8$ 种子串的某一个,其对答案的贡献就是 $\left(f(i-1,0) + f(i-1,1)) \cdot (g(i+m,0) + g(i+m,1)\right)$。

  AC 代码如下,时间复杂度为 $O(n)$:

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

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

int f[N][2], g[N][2];

int main() {
    string s;
    cin >> s;
    int n = s.size();
    s = ' ' + s;
    f[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        f[i][0] = (f[i - 1][0] + f[i - 1][1]) % mod;
        f[i][1] = f[i - 1][0];
    }
    g[n + 1][0] = 1;
    for (int i = n; i; i--) {
        g[i][0] = (g[i + 1][0] + g[i + 1][1]) % mod;
        g[i][1] = g[i + 1][0];
    }
    int ret = 0;
    vector<string> p({"mygo", "m_ygo", "my_go", "myg_o", "m_y_go", "my_g_o", "m_yg_o", "m_y_g_o"});
    for (int i = 1; i <= n; i++) {
        for (auto &t : p) {
            int m = t.size();
            if (i + m - 1 > n) continue;
            bool flag = true;
            for (int j = 0; j < m; j++) {
                if (t[j] == '_') continue;
                if (s[i + j] != t[j]) flag = false;
            }
            if (flag) ret = (ret + 1ll * (f[i - 1][0] + f[i - 1][1]) * (g[i + m][0] + g[i + m][1])) % mod;
        }
    }
    cout << ret;
    
    return 0;
}

 

参考资料

  出题人题解:https://ac.nowcoder.com/discuss/1252622

标签:子串,删除,int,迷茫,tomorin,字符串,mygo
From: https://www.cnblogs.com/onlyblues/p/18032493

相关文章

  • bitmap 位图 底层原理标记的字符串放在哪
    在Redis中,位图(bitmap)是通过字符串(string)类型来实现的,具体来说,位图是存储在Redis字符串中的二进制位数据。Redis字符串一般采用动态字符串实现,最大长度可以达到512MB。对于位图来说,每个二进制位代表一个状态或标记,可以表示非常多的状态信息,同时占用的存储空间很小。当使用......
  • Python 字符串格式化输出
    数字n:int=1000000000print(f'{n:_}')#1_000_000_000print(f'{n:,}')#1,000,000,000对齐var:str='var'#右对齐,使用_填充print(f'{var:_>20}')#_________________var#左对齐,使用#填充print(f'{var:#<20}�......
  • JavaScript语法-字符串模板
    [TOC]##JavaScript模板字符串###代码以下是index.js的部分代码:```onShareAppMessage({const{toName,mainText,fromName}=this.data;debugger;return{title:'叮,您收到一张贺卡~',path:'pages/index/index?toname=${toName}&mai......
  • isdigit函数用法、获得字符串对应的数字
    1.isdigit函数用法语法:#include<ctype.h>intisdigit(intch);使用需要添加头文件#include<ctype>。功能:如果参数是0到9之间的数字字符,函数返回非零值,否则返回零值。2.GetNUmber//获得字符串对应的数字doubleGetNumber(stringstr,intindex){doublenumb......
  • 算法-字符串
    1.反转字符串(LeetCode344)题目:编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间解决这一问题。思路:双指针,左边和右边对应位置的依次交换classSolution{......
  • C# 的布尔类型和字符串类型(模板字符串)
    //布尔类型bollboolb=false;b=1==1;//trueboolb1=1>23;//false//值类型:在代码中初始化类型的时候没有赋值但是系统会自动赋值的叫值类型//byteshortint(default0)longfloatdou......
  • KMP 字符串搜索算法
    KMP字符串搜索算法是Knuth、Morris、Pratt三位在类似的时间段内一起发明的一种字符串搜索算法,该算法的主要原理是利用待查找子串中的某些信息,在匹配失败时能够减少回退的步数算法原理假设现在有一个待搜索的字符串ABABAC,如何利用现有的字符串实现在字符不匹配时尽可能向后调......
  • 【字符串】
    首先创建字符串可以使用单引号、双引号、三单引号和三双引号,其中三引号可以多行定义字符串,Python不支持单字符类型,单字符在Python中也是作为一个字符串使用。我们定义一个变量str='python'语句,它在计算机中的执行顺序是先在内存中创建一个字符串Python,在程序栈寄存器中......
  • 综合练习字符串2
    思路2......
  • 代码随想录 day59 两个字符串的删除操作 编辑距离
    两个字符串的删除操作两种思路如果是以最长公共子序列去理解求出这个子序列长度然后原长减一下就行如果是直接正面求解就是如下解法递推式很好理解初始化意思是当一个串为0长度时需要操作另一个字符串长度次也就是直接赋予下标编辑距离dp[i-1][j-1]+1意......