zoukankan      html  css  js  c++  java
  • CF #344 D. Messenger KMP/Z

    题目链接:http://codeforces.com/problemset/problem/631/D

    给定两个压缩形式的字符串,如a3b5a4k7这样的形式

    问A在B中出现次数。

    分类讨论,如果A是只有一种字符的,则答案数量可能很大,但计算也很简单,直接看B的每一个字符,答案累加上cnt2-cnt1+1

    如果A不是单字符的,则答案至多是B的压缩之后长度的数量级。

    不考虑A的第一个字符,用KMP或者Z函数来计算A的出现情况,如果匹配长度为lenA-1,则检查是否该匹配的第一个字符与A【0】相等且数量大于A【0】的数量,如果匹配长度为lenA-2,则检查是否下一个字符与A最后一个字符是相等的,且数量大于A【lenA-1】的数量。

    写的时候需要仔细,因为涉及到不少下标以及条件判断。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <math.h>
      8 #include <stdlib.h>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #include <ctime>
     14 #include <numeric>
     15 #include <cassert>
     16 
     17 using namespace std;
     18 
     19 const int N=1e6+100;
     20 
     21 
     22 struct Char {
     23     char ch;
     24     long long cnt;
     25     bool operator == (const Char &o) const {
     26         return ch==o.ch&&cnt==o.cnt;
     27     }
     28 };
     29 int z[N];
     30 Char f[N];
     31 void Z(int n) {
     32     z[0]=n;
     33     int L=0,R=0;
     34     for (int i=1;i<n;i++) {
     35         if (i>R) {
     36             L=i,R=i;
     37             while (R<n&&f[R-i]==f[R]) R++;
     38             z[i]=R-L;
     39             R--;
     40         }
     41         else {
     42             int k=i-L;
     43             if (z[k]<R-i+1)
     44                 z[i]=z[k];
     45             else {
     46                 L=i;
     47                 while (R<n&&f[R-i]==f[R]) R++;
     48                 z[i]=R-L;
     49                 R--;
     50             }
     51         }
     52     }
     53 }
     54 Char s[N],t[N];
     55 
     56 
     57 int main() {
     58     int n,m;
     59     scanf("%d %d",&n,&m);
     60     char buf[5];
     61     for (int i=0;i<n;i++) {
     62         long long cnt;
     63         scanf("%I64d-%s",&cnt,buf);
     64         t[i].cnt=cnt;
     65         t[i].ch=buf[0];
     66     }
     67     int k=1;
     68     for (int i=1;i<n;i++) {
     69         if (t[i].ch==t[i-1].ch)
     70             t[k-1].cnt+=t[i].cnt;
     71         else {
     72             t[k++]=t[i];
     73         }
     74     }
     75     n=k;
     76     for (int i=0;i<m;i++) {
     77         long long cnt;
     78         scanf("%I64d-%s",&cnt,buf);
     79         s[i].cnt=cnt;
     80         s[i].ch=buf[0];
     81     }
     82     k=1;
     83     for (int i=1;i<m;i++) {
     84         if (s[i].ch==s[i-1].ch)
     85             s[k-1].cnt+=s[i].cnt;
     86         else {
     87             s[k++]=s[i];
     88         }
     89     }
     90     m=k;
     91 
     92     if (m==1) {
     93         long long ret=0;
     94         for (int i=0;i<n;i++) {
     95             if (t[i].ch==s[0].ch&&t[i].cnt>=s[0].cnt) {
     96                 ret+=t[i].cnt-s[0].cnt+1;
     97             }
     98         }
     99         printf("%I64d
    ",ret);
    100         return 0;
    101     }
    102     int len=0;
    103     for (int i=1;i<m;i++) {
    104         f[len++]=s[i];
    105     }
    106     f[len].ch='#';
    107     f[len].cnt=0;
    108     len++;
    109     int from=len;
    110     for (int i=0;i<n;i++) {
    111         f[len++]=t[i];
    112     }
    113     Z(len);
    114     int ret=0;
    115     for (int i=from+1;i<len;i++) {
    116         int lcp=z[i];
    117         if (t[i-from-1].ch==s[0].ch&&t[i-from-1].cnt>=s[0].cnt) {
    118             if (lcp==m-1)
    119                 ret++;
    120             else if (lcp==m-2) {
    121                 if (s[m-1].ch==t[i-from+lcp].ch&&s[m-1].cnt<=t[i-from+lcp].cnt)
    122                     ret++;
    123             }
    124         }
    125     }
    126     printf("%d
    ",ret);
    127     return 0;
    128 }
    View Code
  • 相关阅读:
    读《大道至简》第6章有感
    Java作业05(动手动脑)
    读《大道至简》第五章有感
    java作业04(动手动脑)
    域名与主机名
    STL 迭代器学习
    数组与链表增删改查效率比较
    智能指针多线程安全问题
    快速乘 学习
    关于TCP三个冗余ACK启动快速重传
  • 原文地址:https://www.cnblogs.com/micrari/p/5245475.html
Copyright © 2011-2022 走看看