zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    自定义类似smarty模板
    PHP函数相关知识点
    cookie的使用和设置
    进程通过内核缓存区请求设备I/O的一些事情
    多线程模型和问题
    C10K问题和多进程模型
    node.js----一个httpserver提交和解析get参数的例子
    nodejs解析url参数的三种方法
    node.js http模块和fs模块上机实验·
    c++中的srand()和rand() 转载 自:http://blog.sina.com.cn/s/blog_624c2c4001012f67.html
  • 原文地址:https://www.cnblogs.com/rtyfcvb/p/8144257.html
Copyright © 2011-2022 走看看