jzoj 3843. 寻找羔羊(agnus) (Standard IO)

1 篇文章 0 订阅
1 篇文章 0 订阅

Description
给定一个由小写字母组成的字符串,寻找包含“agnus”(羔羊)的子串的个数。注意:当且仅当两个子串的起始位置和终点不同时,这两个子串属于不同的子串。

Input
只有一个字符串,表示题中所述的字符串。

Output
仅一个数字,表示满足题意的子串个数。

Sample Input

agnusbgnus

Sample Output
6
【样例解释】
6个子串分别是:agnus、agnusb、agnusbg、agnusbgn、agnusbgnu、agnusbgnus。

Data Constraint
对于 40%的数据,字符串长度<=1000
对于 100%的数据,字符串长度<=30000

//written by zzy

题目大意:

给你个字符串,求这个串中有多少个子串(字母连续)中有agnus

题解:

容斥,用总的所有子串个数减去不合法的子串个数
例如:S为
XXagnusXXX
1234567890 1234567890 1234567890
总的子串个数为 10 ∗ ( 10 + 1 ) / 2 = 55 10*(10+1)/2=55 10(10+1)/2=55
其中 s [ 1 − 6 ] s[1-6] s[16], s [ 4 − 10 ] s[4-10] s[410]的所有子串不合法,总答案减去 6 ∗ ( 6 + 1 ) / 2 + 7 ∗ ( 7 + 1 ) / 2 = 49 6*(6+1)/2+7*(7+1)/2=49 6(6+1)/2+7(7+1)/2=49
s [ 4 − 6 ] s[4-6] s[46]中的所有子串被减了两次,要加回 3 ∗ ( 3 + 1 ) / 2 = 6 3*(3+1)/2=6 3(3+1)/2=6
答案为 55 − 49 + 6 = 12 55-49+6=12 5549+6=12

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 30005
using namespace std;

int i,j,n=0,m,p,l,ans,re;
int f[N];
char s[N];

int num(int x) {
	return x*(x+1)/2;
}

int main()
{
	scanf("%s",s);
	l=strlen(s);
	ans=num(l);
	for (i=0;i<l;i++) 
	 if (s[i]=='a'&&s[i+1]=='g'&&s[i+2]=='n'&&s[i+3]=='u'&&s[i+4]=='s')
	  f[++n]=1,i+=4,re++; 
	  else f[++n]=0;
	p=0;
	for (i=1;i<=n;i++)
	 if (f[i]==1) {
        if (p==0) ans-=num(i+3); 
        else ans-=num(i-p+7);
        p=i;
	 }
	ans-=num(n-p+4);
	ans+=re*6; 
	printf("%d",ans);
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值