[CF1538E] Funny Substrings (模拟)

题面

该场 Div. 3 最“难”的一道题:Funny Substrings
O I D \tt OID OID 队长喜欢玩字符串,因为 “ O n e I n D a r k ” \tt “OneInDark” OneInDark 是一个望而生畏的字符串。

O I D \tt OID OID 会进行 N \tt N N 次操作,每次操作形如以下两种之一:

  • x := S : x 是变量名称,S 是一个具体的字符串,:= 符号两边都有空格。 O I D \tt OID OID此时的 x 叫做 S Y SY SY 变量。该操作意思是把 x 赋值为字符串 S。
  • x = a + b : x,a,b 是变量名称,= 符号和 + 符号两边都有空格。 O I D \tt OID OID此时的 x 也叫做 S Y SY SY 变量。该操作意思是把 x 赋值为 a 和 b 首尾拼接起来的字符串。保证 a 和 b 在此操作之前作为 S Y SY SY 变量出现过。

现在问你,在最后一次出现的 S Y SY SY 变量储存的字符串中,字符串 haha 作为子串出现过多少次。比如:hahahahahaha 中出现了 3 次。

一共 T ≤ 1 0 3 \tt T\leq10^3 T103 组数据,每组数据中 1 ≤ N ≤ 50 \tt1\leq N\leq50 1N50 1 ≤ ∣ S ∣ ≤ 5 \tt1\leq|S|\leq5 1S5 1 ≤ ∣ 变 量 名 ∣ ≤ 5 \tt1\leq|变量名|\leq5 15

题解

(我看这道题过的人最少,姑且认为它难吧)

不难发现,最终的字符串长度可能超过 long long 范围,因此,直接 string 模拟不是个好方法。

我们会发现,对于一个字符串,有用的信息可以整理成一个三元组 { l ( s t r i n g ) , x ( l o n g   l o n g ) , r ( s t r i n g ) } \tt\{l(string),x(long~long),r(string)\} {l(string),x(long long),r(string)},分别表示:该字符串最左边 3 个(也许不足 3 个)字符,该字符串中 haha 的出现次数,该字符串最右边 3 个(也许不足 3 个)字符。

这个不难处理。关键是这样的三元组可以方便地定义 a + b 操作,返回另一个三元组:

  • x a \tt x_a xa x b \tt x_b xb 加起作为 x \tt x x ,再把 r a \tt r_a ra l b \tt l_b lb 拼起来(长度不超过 6),统计里面的 haha 数量,也加到 x \tt x x 里面去。
  • l \tt l l 赋为 l a \tt l_a la ,如果长度不足 3,再把 l b \tt l_b lb 拼在 l \tt l l 后面,把长度超过 3 的砍掉。
  • r \tt r r 赋为 r b \tt r_b rb ,如果长度不足 3,再把 r a \tt r_a ra 拼在 r \tt r r 前面,把长度超过 3 的砍掉。

这样就做出这道模拟题了,中间的字符串操作,可以暴力用 string 或者 char*+sprintf,时间足够。对于每个变量怎么存三元组,你可以用哈希也可以用 map

CODE

#include<set>
#include<map>
#include<queue>
#include<ctime>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 105
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
#define eps 1e-9
LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
int n,m,i,j,s,o,k;
struct it{
	char l[5],r[5];
	LL nm;it(){memset(l,0,sizeof(l));memset(r,0,sizeof(r));nm=0;}
	it(char *L,char *R,LL N){
		strncpy(l,L,3);nm=N;memset(r,0,sizeof(r));
		int le = strlen(R);
		for(int i = max(le-3,0),j=0;i < le;i ++,j ++) r[j]=R[i];
	}
};
it operator + (it a,it b) {
	char ss[10]; int ls; LL as = a.nm+b.nm;
	sprintf(ss,"%s%s",a.r,b.l);
	ls = strlen(ss);
	for(int i = 0;i <= ls-4;i ++) if(ss[i]=='h'&&ss[i+1]=='a'&&ss[i+2]=='h'&&ss[i+3]=='a') as ++;
	char rel[10],rer[10];
	if(strlen(a.l) < 3) sprintf(rel,"%s%s",a.l,b.l);
	else strcpy(rel,a.l);
	if(strlen(b.r) < 3) sprintf(rer,"%s%s",a.r,b.r);
	else strcpy(rer,b.r);
	return it(rel,rer,as);
}
map<string,it> mp;
int main() {
	int T = read();
	while(T --) {
		n = read();
		mp.clear();
		string las;
		for(int i = 1;i <= n;i ++) {
			string A,md,B,C;
			cin>>A;
			las = A;
			cin>>md;
			if(md[0]==':') {
				char ss[15]; int le,as = 0;
				scanf("%s",ss); le = strlen(ss);
				for(int i = 0;i <= le-4;i ++) {
					 if(ss[i]=='h'&&ss[i+1]=='a'&&ss[i+2]=='h'&&ss[i+3]=='a') as ++;
				}
				mp[A] = it(ss,ss,(LL)as);
			}
			else {
				cin>>B;cin>>md;cin>>C;
				mp[A] = mp[B] + mp[C];
			}
		}
		printf("%lld\n",mp[las].nm);
	}
	return 0;
}
posted @ 2021-06-16 17:19  DD_XYX  阅读(44)  评论(0)    收藏  举报