CF 631D KMP/Z
Posted Live In A Dream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 631D KMP/Z相关的知识,希望对你有一定的参考价值。
给定两个压缩形式的字符串,如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\n",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\n",ret); 127 return 0; 128 }
以上是关于CF 631D KMP/Z的主要内容,如果未能解决你的问题,请参考以下文章