zoukankan      html  css  js  c++  java
  • NOIP2015提高组复赛B 子串

    题目链接:https://ac.nowcoder.com/acm/contest/263/B

    题目大意:

      略

    分析:

      设preA(i)为字符串A中第1个字符到第i个字符构成的字符串。

      设preB(i)为字符串B中第1个字符到第i个字符构成的字符串。

      设所要解决的问题为problem(A, B, k)。

      设dp[i][j][h]为problem(preA(i), preB(j), h)的答案。

      于是problem(A, B, k)的答案就是dp[n][m][k]。

    以下几种情况是容易得知的:

      当 j == 0 && h == 0时,dp[i][0][0] = 1,这是因为在preA(i)中选0个子串只有一种选法,连起来是空串,preB(0)也是空串。

      当 i < h 时,即preA(i)选不出h个子串时,dp[i][j][h] = 0。

      当 i < j 时,即preA(i)长度小于preB(j)时,dp[i][j][h] = 0。

      当 h > j 时,即所需要选的子串数目大于于preB(j)时,dp[i][j][h] = 0,因为每个字串至少贡献一个长度。

      当 j != 0 && h == 0时,由于preB(j)不是空串,所以dp[i][j][h] = 0。

    现在开始推dp[i + 1][j][h]的递推关系(由于上面所述的情况,i = 0时候的所有情况都是已知的,所以很自然地想要用i去推i + 1):

      作为A[i + 1]这个新加进来的字符,有2种情况:

        1:A[i + 1] != B[j],这种情况下A[i + 1]并不会对答案有所贡献,有和没有一样,所以dp[i + 1][j][h] = dp[i][j][h]。

        2:A[i + 1] == B[j],这种情况下dp[i + 1][j][h]的构成分为3种:

          (1):不选A[i + 1],这和A[i + 1] != B[j]一样,dp[i + 1][j][h] = dp[i][j][h]。

          (2):单独选A[i + 1],这时dp[i + 1][j][h] = dp[i][j - 1][h - 1]。

          (3):A[i + 1]是和A[i]一起被选上的,这种情况下和单选选A[i + 1]差不多,不过h不用减,又因为dp[i][j - 1][h]里面还包含A[i + 1]和A[i]不一起的情况,即没选A[i]的情况,要减去这种情况,所以答案为dp[i + 1][j][h] = dp[i][j - 1][h] - dp[i - 1][j - 1][h]。

    注意点:数组直接开3维会爆内存,应该用滚动数组。

    70分代码如下(超内存):

      1 #pragma GCC optimize("Ofast")
      2 #include <bits/stdc++.h>
      3 using namespace std;
      4  
      5 #define INIT() std::ios::sync_with_stdio(false);std::cin.tie(0);
      6 #define Rep(i,n) for (int i = 0; i < (n); ++i)
      7 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
      8 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
      9 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
     10 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
     11 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
     12 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
     13  
     14 #define pr(x) cout << #x << " = " << x << "  "
     15 #define prln(x) cout << #x << " = " << x << endl
     16  
     17 #define LOWBIT(x) ((x)&(-x))
     18  
     19 #define ALL(x) x.begin(),x.end()
     20 #define INS(x) inserter(x,x.begin())
     21  
     22 #define ms0(a) memset(a,0,sizeof(a))
     23 #define msI(a) memset(a,inf,sizeof(a))
     24 #define msM(a) memset(a,-1,sizeof(a))
     25 
     26 #define MP make_pair
     27 #define PB push_back
     28 #define ft first
     29 #define sd second
     30  
     31 template<typename T1, typename T2>
     32 istream &operator>>(istream &in, pair<T1, T2> &p) {
     33     in >> p.first >> p.second;
     34     return in;
     35 }
     36  
     37 template<typename T>
     38 istream &operator>>(istream &in, vector<T> &v) {
     39     for (auto &x: v)
     40         in >> x;
     41     return in;
     42 }
     43  
     44 template<typename T1, typename T2>
     45 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
     46     out << "[" << p.first << ", " << p.second << "]" << "
    ";
     47     return out;
     48 }
     49  
     50 typedef long long LL;
     51 typedef unsigned long long uLL;
     52 typedef pair< double, double > PDD;
     53 typedef set< int > SI;
     54 typedef vector< int > VI;
     55 const double EPS = 1e-10;
     56 const int inf = 1e9 + 9;
     57 const LL mod = 1e9 + 7;
     58 const int maxN = 1e5 + 7;
     59 const LL ONE = 1;
     60 
     61 int n, m, k;
     62 string A, B;
     63 LL dp[1007][207][207];
     64 
     65 void solve() {
     66     For(i, 0, n) {
     67         For(j, 0, m) {
     68             For(h, 0, k) {
     69                 if(j == 0 && h == 0) dp[i][j][h] = 1;
     70                 else if(i < h || i < j || h > j || h == 0) dp[i][j][h] = 0;
     71                 else if(A[i] == B[j]) {
     72                     dp[i][j][h] += dp[i - 1][j][h]; // 不选A[i] 
     73                     dp[i][j][h] %= mod;
     74                     dp[i][j][h] += dp[i - 1][j - 1][h - 1]; // 单独选A[i]  
     75                     dp[i][j][h] %= mod;   
     76                     if(i >= 2) {
     77                         // A[i]和A[i - 1]连着的情况 
     78                         dp[i][j][h] += dp[i - 1][j - 1][h]; // 先加一下所有不单独选A[i]的情况 
     79                         dp[i][j][h] %= mod;
     80                         dp[i][j][h] -= dp[i - 2][j - 1][h]; // 再减去不连着的情况 
     81                         dp[i][j][h] += mod;
     82                         dp[i][j][h] %= mod;
     83                     }
     84                     dp[i][j][h] %= mod;
     85                 }
     86                 else if(A[i] != B[j]) dp[i][j][h] = dp[i - 1][j][h];
     87             }
     88         }
     89     }
     90     
     91     
     92 }
     93 
     94 int main(){
     95     INIT();
     96     cin >> n >> m >> k >> A >> B;
     97     A.insert(0, "#"); //< 让下标从1开始 
     98     B.insert(0, "#"); 
     99     
    100     solve();
    101     
    102     cout << dp[n][m][k] << endl;
    103     return 0;
    104 }
    View Code

    100分代码如下:

     1 #pragma GCC optimize("Ofast")
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4  
     5 #define INIT() std::ios::sync_with_stdio(false);std::cin.tie(0);
     6 #define Rep(i,n) for (int i = 0; i < (n); ++i)
     7 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
     8 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
     9 #define ForLL(i, s, t) for (LL i = LL(s); i <= LL(t); ++i)
    10 #define rForLL(i, t, s) for (LL i = LL(t); i >= LL(s); --i)
    11 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
    12 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
    13  
    14 #define pr(x) cout << #x << " = " << x << "  "
    15 #define prln(x) cout << #x << " = " << x << endl
    16  
    17 #define LOWBIT(x) ((x)&(-x))
    18  
    19 #define ALL(x) x.begin(),x.end()
    20 #define INS(x) inserter(x,x.begin())
    21  
    22 #define ms0(a) memset(a,0,sizeof(a))
    23 #define msI(a) memset(a,inf,sizeof(a))
    24 #define msM(a) memset(a,-1,sizeof(a))
    25 
    26 #define MP make_pair
    27 #define PB push_back
    28 #define ft first
    29 #define sd second
    30  
    31 template<typename T1, typename T2>
    32 istream &operator>>(istream &in, pair<T1, T2> &p) {
    33     in >> p.first >> p.second;
    34     return in;
    35 }
    36  
    37 template<typename T>
    38 istream &operator>>(istream &in, vector<T> &v) {
    39     for (auto &x: v)
    40         in >> x;
    41     return in;
    42 }
    43  
    44 template<typename T1, typename T2>
    45 ostream &operator<<(ostream &out, const std::pair<T1, T2> &p) {
    46     out << "[" << p.first << ", " << p.second << "]" << "
    ";
    47     return out;
    48 }
    49  
    50 typedef long long LL;
    51 typedef unsigned long long uLL;
    52 typedef pair< double, double > PDD;
    53 typedef set< int > SI;
    54 typedef vector< int > VI;
    55 const double EPS = 1e-10;
    56 const int inf = 1e9 + 9;
    57 const LL mod = 1e9 + 7;
    58 const int maxN = 1e5 + 7;
    59 const LL ONE = 1;
    60 
    61 int n, m, k;
    62 string A, B;
    63 LL dp[3][207][207];
    64 
    65 void solve() {
    66     For(i, 0, n) {
    67         For(j, 0, m) {
    68             For(h, 0, k) {
    69                 dp[i % 3][j][h] = 0; // 归零 
    70                 if(j == 0 && h == 0) dp[i % 3][j][h] = 1;
    71                 else if(i < h || i < j || h > j || h == 0) dp[i % 3][j][h] = 0;
    72                 else if(A[i] == B[j]) {
    73                     dp[i % 3][j][h] += dp[(i - 1) % 3][j][h]; // 不选A[i] 
    74                     dp[i % 3][j][h] += dp[(i - 1) % 3][j - 1][h - 1]; // 单独选A[i] 
    75                     if(i >= 2) {
    76                         // A[i]和A[i - 1]连着的情况 
    77                         dp[i % 3][j][h] += dp[(i - 1) % 3][j - 1][h]; // 先加一下所有不单独选A[i]的情况 
    78                         dp[i % 3][j][h] -= dp[(i - 2) % 3][j - 1][h]; // 再减去不连着的情况 
    79                         dp[i % 3][j][h] += mod;
    80                     }
    81                 }
    82                 else if(A[i] != B[j]) dp[i % 3][j][h] = dp[(i - 1) % 3][j][h];
    83                 dp[i % 3][j][h] %= mod;
    84             }
    85         }
    86     }
    87 }
    88 
    89 int main(){
    90     INIT();
    91     cin >> n >> m >> k >> A >> B;
    92     A.insert(0, "#"); //< 让下标从1开始 
    93     B.insert(0, "#"); 
    94     
    95     solve();
    96     
    97     cout << dp[n % 3][m][k] << endl;
    98     return 0;
    99 }
    View Code
  • 相关阅读:
    nginx优化配置
    mysql查看变量/配置文件位置
    关于ubuntu的ssh远程登录的问题
    ubuntu镜像下载地址
    百度地图标注地点
    Yii常用方法
    python_将一组数据展示成直方图(以list为例)
    opencv_形态学结构化元素对形态学图像处理的影响
    C语言学习_从VC++6.0开始
    SVM原理(1)
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/10747406.html
Copyright © 2011-2022 走看看