• codeforces 282(div1)B Obsessive String


    这题题意真的是玄学==读了半年

    题目在这里

    题意:给两个串s,t,0<|s|,|t|<=1e5,现在要把s分割成不重合的k段,每段的起点是a[i],终点是b[i].也就是串s[a[i]]s[a[i]+1]s[a[i]+2].....s[b[i]]这一段。要求每段都有一个子串是t。求有多少种分割的方案
    思路:首先不难想到这样暴力:dp[i]表示把i作为最后一段子串终止点的方案数dp[i] = dp[j] *(si - j) + dp[j + 1] * (si - j - 1).....+dp[si-1]*(1)
    si是最后一段子串想要包含t的最后面的开始点。然后观察等式右边发现这个公式可以维护一个前缀答案和tmp和前缀和sum,然后si每向右边移动一位。sum就加上dp[si],tmp就加上sum;
    每个点的si可以用KMP来求==具体见代码:

    代码:

     #include<bits/stdc++.h>
     using namespace std;
     typedef long long ll;
     const int maxn = 1e5 + 10;
     const ll mod = 1e9 + 7;
     char s[maxn] , t[maxn];
     int nxt[maxn];
     bool mat[maxn];
     ll dp[maxn];
     int lastmat[maxn];
     void get_next(){
         int lent = strlen(t + 1)+1;
         nxt[0] = 0;
         nxt[1] = 0;
         int i = 2 , j = 0;
         while(i <= lent){
            if(j != 0 && t[i - 1] != t[j]) j = nxt[j];
            else nxt[i++] = ++j;
         }
         for(int i = 1; i <= lent;i++){
            int xt = nxt[i];
            while(t[i] == t[xt]&&xt != 0) nxt[i] = nxt[xt] ,xt = nxt[xt];
         }
    }
     void KMP(){
       memset(mat,0,sizeof(mat));
       int lent = strlen(t + 1) + 1;
       int lens = strlen(s + 1);
       int j = 1;
       for(int i = 1; i <= lens;i++){
            while(j != 0 && s[i] != t[j]) j = nxt[j];
            j++;
            if(j == lent) mat[i] = 1 , j = nxt[j];
       }
    }
    void init(){
        int si = 0;
        int lens = strlen(s + 1);
        int lent = strlen(t + 1);
        for(int i = 1 ; i <= lens;i++){
             if(mat[i]){
                si = i - lent + 1;
             }
             lastmat[i] = si;
        }
    }
     int main()
     {
         while(~scanf("%s%s",s+1,t+1)){
            get_next();
            KMP();
            init();
            memset(dp,0,sizeof(dp));
            dp[0] = 1;
            ll sum = 0;
            ll tmp = 0;
            int lens = strlen(s + 1);
            ll ans = 0;
            int si = 0;
            for(int i = 1; i <= lens;i++){
                while(si < lastmat[i]){
                    sum += dp[si++];
                    if(sum >= mod) sum -= mod;
                    tmp += sum;
                    if(tmp >= mod) tmp -= mod;
                }
                dp[i] = tmp;
                ans += tmp;
                if(ans >= mod) ans -= mod;
            }
            printf("%I64d
    ",ans);
         }
     }
    View Code
  • 相关阅读:
    Activity的启动模式
    Assets和Raw区别
    手机自动跑脚本
    系统隐式 Intent
    判断是否为小屏幕设备
    C语言数组初始化方式
    windows10环境下gcc环境变量的配置
    UE4.22编辑器界面操控设置(4)
    windows10下JDK9的环境配置
    分布式ID生成解决方案之snowflake(雪花算法)
  • 原文地址:https://www.cnblogs.com/rtyfcvb/p/8144257.html
Copyright © 2020-2023  润新知