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[1−6],
s
[
4
−
10
]
s[4-10]
s[4−10]的所有子串不合法,总答案减去
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[4−6]中的所有子串被减了两次,要加回
3
∗
(
3
+
1
)
/
2
=
6
3*(3+1)/2=6
3∗(3+1)/2=6
答案为
55
−
49
+
6
=
12
55-49+6=12
55−49+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);
}