(线段树+kmp) 1828

来源:互联网 发布:ida pro linux 破解版 编辑:程序博客网 时间:2024/05/19 14:39

题意:给出一个字符串,有一些字母是喜欢的,有些不喜欢。

           求出这个串的连续子串中不喜欢的长度不超过K的数目,其中重复的子串只算一个


思路:先是用线段树来记录每段字符串中不喜欢字母的个数。

           用KMP的前一部分来处理子串的的每一段,,找到前面已经有该子串的



注意:要把判断子串的if放在find()外面,这样就减少了很多不必要的fin(),,这才在时间上才够。。


#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<set>using namespace std;#define N 1555#define H 100007bool  map[N][N];int n;string s;string b;set<string> go;struct my{int left,right;int value;int mid;}t[4*N];int next[N];void build(int cur,int l,int r){//cout<<cur<<" "<<l<<' '<<r<<endl;t[cur].left=l;t[cur].right=r;t[cur].mid=(l+r)>>1;if (l!=r){build(cur<<1,l,t[cur].mid);build(cur<<1|1,t[cur].mid+1,r);t[cur].value=t[cur<<1].value+t[cur<<1|1].value;}else{if (b[s[l-1]-'a']=='1')t[cur].value=0;elset[cur].value=1;//cout<<l<<' '<<cur<<' '<<b[s[l-1]-'a']<<' '<<t[cur].value<<endl;}}int find(int cur,int l,int r){//cout<<cur<<' '<<l<<' '<<r<<' '<<t[cur].value<<endl;if (l==t[cur].left && r==t[cur].right){return t[cur].value;}int m=t[cur].mid;int L=cur<<1,R=cur<<1|1;if (r<=m)return find(L,l,r);else if (l>m)return find(R,l,r);else{return find(L,l,m)+find(R,m+1,r);}}void get_next(int i){int j=i-1;next[i]=j;int k=j;while  (i<n){if (j==k || s[i]==s[j]){i++;j++;next[i]=j;}elsej=next[j];}}int main(){freopen("in.txt","r",stdin);int i,j,k;int ncases;cin>>ncases;string cur;while (ncases--){cin>>s;cin>>b;scanf("%d",&k);n=s.size();build(1,1,n);int ans=0;go.clear();for (i=1;i<=n;i++)for (j=i;j<=n;j++)map[i][j]=false;for (i=1;i<=n;i++){get_next(i-1);for (j=i;j<=n;j++) if (next[j]>=i){map[j-(next[j]-i)][j]=true;}}for (i=1;i<=n;i++){for (j=i;j<=n;j++)  if (!map[i][j]) if (find(1,i,j)<=k){//if (!map[i][j]){//cout<<i<<' '<<j<<endl;ans++;} }elsebreak;}cout<<ans<<endl;}return 0;}




Description

Minakami Yuki 很喜欢字符串,作为一个犯中二病的熊孩子,她只喜欢某些特定的小写字母,如果一个字符串包含了多于K个她不喜欢的字母,她就认为这是一个“坏串”。有一天她看到了一个只由小写字母组成的字符串,她想知道这个字符串的哪些子串不是“坏串”。因为她还要努力研究奇怪的哲学知识,这个问题就由你来计算了。
注意注意如果一个相同的子串出现在了原串的多个位置,只能算作一次喵~

Input

本题有多组测试数据,Input的第一行是一个整数T(T<=100),是测试数据的组数。
接下来T组数据,每组由三行构成。

第一行是一个字符串S,长度不超过1500,是Yuki看到的字符串。
第一行是一个长度为26的01串,代表Yuki喜不喜欢每个字母,从'a'到'z'。'0'代表不喜欢,'1'代表喜欢。
第三行是一个整数K,0<=K<=(S的长度),表示子串中最多所能包含的不喜欢的字母个数

Output

输出T行,每行一个整数,即满足条件子串的个数

Sample Input

2
ababab
01000000000000000000000000
1
acbacbacaa
00000000000000000000000000
2

Sample Output

5
8

Hint

子串是字符串中连续的一段,也可以包含原串本身。


原创粉丝点击