http://codeforces.com/contest/963/problem/D

题解:https://www.cnblogs.com/Blue233333/p/8881614.html

记M为n个串的总长,L为s的长度

询问串的不同的长度只会有sqrt(M)级别个

(最差的情况是串长为1,2,3,...,x,此时M=(x+1)x/2,因此x是sqrt(M)级别的)

s的子串中,长度为特定值k的子串个数是L级别的,

由于各个字符串互不相同,这就相当于n个串中所有长度为k的串,分别计算出它们在s中出现次数,各个计算结果的和是L级别的

因此只要设计对于每一个询问串都是O(串长+出现次数)的算法就行了


花了好长时间写了个后缀自动机字符串匹配啊。。。。莫不是搞复杂了

代码1.(using连用多个是c++17的,曾经还CE了)

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
typedef long long LL;
char s[],ss[];
int ll,x[],l2;
int pp[];
vector<int> vv[];
set<int> sss[];
int n,ans[];
int lll[];
namespace SAM
{
int mem,np,root;
int len[],par[];
int trans[][];
int posl[],posr[];
void append(int ch)
{
int p=np;np=++mem;len[np]=len[p]+;
for(;p&&!trans[p][ch];p=par[p]) trans[p][ch]=np;
if(!p) par[np]=root;
else
{
int q=trans[p][ch];
if(len[q]==len[p]+) par[np]=q;
else
{
int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+;
for(;p&&trans[p][ch]==q;p=par[p]) trans[p][ch]=nq;
}
}
}
void build()
{
np=root=++mem;
int i,now;
for(i=;i<=ll;i++) append(s[i]-'a'),pp[i]=np,sss[np].insert(i);
for(i=;i<=ll;i++)
{
for(now=pp[i];now!=root&&!posr[now]&&!posl[now];now=par[now])
{
posl[now]=i-len[par[now]];posr[now]=i-len[now]+;
}
}
}
}
namespace ST
{
int ch[][];
using SAM::par;
void build()
{
int i;
for(i=;i<=SAM::mem;i++)
{
if(par[i])
{
ch[par[i]][s[SAM::posl[i]]-'a']=i;
}
}
}
/*
void out()
{
int i,j,k;using SAM::len,SAM::posl,SAM::posr;
for(i=1;i<=SAM::mem;i++)
{
for(j=0;j<26;j++)
{
if(ch[i][j])
{
printf("%d %d ",i,ch[i][j]);
for(k=posl[ch[i][j]];k>=posr[ch[i][j]];k--) putchar(s[k]);
puts("");
}
}
}
}
*/
}
void work(int tt)
{
using SAM::root,SAM::posl,SAM::posr,ST::ch;
int i,now=root,j,k;
for(i=l2;i>=;)
{
now=ch[now][ss[i]-'a'];
if(!now) return;
for(j=i,k=posl[now];j>=&&k>=posr[now];j--,k--)
if(ss[j]!=s[k])
return;
i-=posl[now]-posr[now]+;
//printf("b%d %d %d %d\n",now,i,posl[now],posr[now]);
}
vv[now].push_back(tt);//printf("a%d\n",now);
}
queue<int> q;int in[];
void work2()
{
using SAM::mem,SAM::par;
int i,j,t,l,r;vector<int> tmp;
for(i=;i<=mem;i++) if(par[i]) in[par[i]]++;
for(i=;i<=mem;i++) if(!in[i]) q.push(i);
while(!q.empty())
{
t=q.front();q.pop();
if(vv[t].size())
{
tmp.clear();
for(auto k:sss[t]) tmp.push_back(k);
//for(i=0;i<tmp.size();i++) printf("%d ",tmp[i]);puts("");
}
for(auto p:vv[t])
{
for(i=,j=x[p]-;j<tmp.size();i++,j++)
{
ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
}
}
if(par[t])
{
if(sss[par[t]].size()<sss[t].size()) swap(sss[par[t]],sss[t]);
for(auto k:sss[t]) sss[par[t]].insert(k);
sss[t].clear();
in[par[t]]--;
if(!in[par[t]]) q.push(par[t]);
}
}
}
int main()
{
int i;
scanf("%s",s+);ll=strlen(s+);
SAM::build();ST::build();
//ST::out();return 0;
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%s",&x[i],ss+);l2=lll[i]=strlen(ss+);
work(i);
}
memset(ans,0x3f,sizeof(ans));
work2();
for(i=;i<=n;i++)
printf("%d\n",ans[i]==0x3f3f3f3f?-:ans[i]);
return ;
}

代码2:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
typedef long long LL;
char s[],ss[];
int ll,x[],l2;
int pp[];
vector<int> vv[];
set<int> sss[];
int n,ans[];
int lll[];
namespace SAM
{
int mem,np,root;
int len[],par[];
int trans[][];
int posl[],posr[];
void append(int ch)
{
int p=np;np=++mem;len[np]=len[p]+;
for(;p&&!trans[p][ch];p=par[p]) trans[p][ch]=np;
if(!p) par[np]=root;
else
{
int q=trans[p][ch];
if(len[q]==len[p]+) par[np]=q;
else
{
int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+;
posl[nq]=posl[q];posr[nq]=posl[q]-(len[nq]-len[par[nq]])+;posl[q]=posr[nq]-;
for(;p&&trans[p][ch]==q;p=par[p]) trans[p][ch]=nq;
}
}
}
void build()
{
np=root=++mem;
int i,now;
for(i=;i<=ll;i++)
{
append(s[i]-'a'),sss[np].insert(i);
for(now=np;now!=root&&!posr[now]&&!posl[now];now=par[now])
{
posl[now]=i-len[par[now]];posr[now]=i-len[now]+;
}
}
}
}
namespace ST
{
int ch[][];
using SAM::par;
void build()
{
int i;
for(i=;i<=SAM::mem;i++)
{
if(par[i])
{
ch[par[i]][s[SAM::posl[i]]-'a']=i;
}
}
}
/*
void out()
{
int i,j,k;using SAM::len,SAM::posl,SAM::posr;
for(i=1;i<=SAM::mem;i++)
{
for(j=0;j<26;j++)
{
if(ch[i][j])
{
printf("%d %d ",i,ch[i][j]);
for(k=posl[ch[i][j]];k>=posr[ch[i][j]];k--) putchar(s[k]);
puts("");
}
}
}
}
*/
}
void work(int tt)
{
using SAM::root,SAM::posl,SAM::posr,ST::ch;
int i,now=root,j,k;
for(i=l2;i>=;)
{
now=ch[now][ss[i]-'a'];
if(!now) return;
for(j=i,k=posl[now];j>=&&k>=posr[now];j--,k--)
if(ss[j]!=s[k])
return;
i-=posl[now]-posr[now]+;
//printf("b%d %d %d %d\n",now,i,posl[now],posr[now]);
}
vv[now].push_back(tt);//printf("a%d\n",now);
}
queue<int> q;int in[];
void work2()
{
using SAM::mem,SAM::par;
int i,j,t;vector<int> tmp;
for(i=;i<=mem;i++) if(par[i]) in[par[i]]++;
for(i=;i<=mem;i++) if(!in[i]) q.push(i);
while(!q.empty())
{
t=q.front();q.pop();
if(vv[t].size())
{
tmp.clear();
for(auto k:sss[t]) tmp.push_back(k);
//for(i=0;i<tmp.size();i++) printf("%d ",tmp[i]);puts("");
}
for(auto p:vv[t])
{
for(i=,j=x[p]-;j<tmp.size();i++,j++)
{
ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
}
}
if(par[t])
{
if(sss[par[t]].size()<sss[t].size()) swap(sss[par[t]],sss[t]);
for(auto k:sss[t]) sss[par[t]].insert(k);
sss[t].clear();
in[par[t]]--;
if(!in[par[t]]) q.push(par[t]);
}
}
}
int main()
{
int i;
scanf("%s",s+);ll=strlen(s+);
SAM::build();ST::build();
//ST::out();return 0;
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%s",&x[i],ss+);l2=lll[i]=strlen(ss+);
work(i);
}
memset(ans,0x3f,sizeof(ans));
work2();
for(i=;i<=n;i++)
printf("%d\n",ans[i]==0x3f3f3f3f?-:ans[i]);
return ;
}

还有一份看上去很高妙的bitset字符串匹配(不是自己写的,先记一下)

来源:http://codeforces.com/contest/963/submission/37784765

 #include<bits/stdc++.h>
#define N 100005
using namespace std;
bitset<N> b[],tmp;
char s[N],t[N];
int main(){
scanf("%s",s);
int n=strlen(s);
for (int i=;i<n;i++)
b[s[i]-'a'][i]=;
int Q; scanf("%d",&Q);
while (Q--){
int k; scanf("%d%s",&k,t);
int m=strlen(t);
tmp.set();
for (int i=;i<m;i++)
tmp&=b[t[i]-'a']>>i;
if (tmp.count()<k){
puts("-1");
continue;
}
vector<int> v;
for (int i=tmp._Find_first();i<n;i=tmp._Find_next(i))
v.push_back(i);
int ans=1e9;
for (int i=;i+k-<v.size();i++)
ans=min(ans,v[i+k-]-v[i]+m);
printf("%d\n",ans);
}
}

就是搞复杂了。。

要找一个字符串,只要在后缀自动机上一位一位找过去,保证最后到达的一定也是后缀树上的对应节点。。。

 #pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
typedef long long LL;
char s[],ss[];
int ll,x[],l2;
int pp[];
vector<int> vv[];
set<int> sss[];
int n,ans[];
int lll[];
int teststet;
int ssss; namespace SAM
{
int mem,np,root;
int len[],par[];
int trans[][];
void append(int ch)
{
int p=np;np=++mem;len[np]=len[p]+;
for(;p&&!trans[p][ch];p=par[p]) trans[p][ch]=np;
if(!p) par[np]=root;
else
{
int q=trans[p][ch];
if(len[q]==len[p]+) par[np]=q;
else
{
int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq;
memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+;
for(;p&&trans[p][ch]==q;p=par[p]) trans[p][ch]=nq;
}
}
}
void build()
{
np=root=++mem;
int i;
for(i=;i<=ll;i++)
{
append(s[i]-'a'),sss[np].insert(i);
}
}
}
void work(int tt)
{
using SAM::trans;
int i,now=SAM::root;
for(i=;i<=l2;i++)
{
now=trans[now][ss[i]-'a'];
}
vv[now].push_back(tt);
}
queue<int> q;int in[];
void work2()
{
using SAM::mem;using SAM::par;
int i,j,t;vector<int> tmp;
for(i=;i<=mem;i++) if(par[i]) in[par[i]]++;
for(i=;i<=mem;i++) if(!in[i]) q.push(i);
while(!q.empty())
{
t=q.front();q.pop();
if(vv[t].size())
{
tmp.clear();
for(auto k:sss[t]) tmp.push_back(k);
}
for(auto p:vv[t])
{
for(i=,j=x[p]-;j<tmp.size();i++,j++)
{
ans[p]=min(ans[p],tmp[j]-tmp[i]+lll[p]);
}
}
if(par[t])
{
if(sss[par[t]].size()<sss[t].size()) swap(sss[par[t]],sss[t]);
for(auto k:sss[t]) sss[par[t]].insert(k);
sss[t].clear();
in[par[t]]--;
if(!in[par[t]]) q.push(par[t]);
}
}
}
int main()
{
int i;
scanf("%s",s+);ll=strlen(s+);
SAM::build();
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%s",&x[i],ss+);l2=lll[i]=strlen(ss+);
work(i);
}
int aefsaf;
memset(ans,0x3f,sizeof(ans));
work2();
for(i=;i<=n;i++)
printf("%d\n",ans[i]==0x3f3f3f3f?-:ans[i]);
return ;
}

Frequency of String CodeForces - 963D的更多相关文章

  1. Minimal string CodeForces - 797C

    Minimal string CodeForces - 797C 题意:有一个字符串s和空串t和u,每次操作可以将s的第一个字符取出并删除然后放到t的最后,或者将t的最后一个字符取出并删除然后放到u的 ...

  2. CodeForces - 963D:Frequency of String (bitset暴力搞)

    You are given a string ss. You should answer nn queries. The ii-th query consists of integer kiki an ...

  3. Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1)D. Frequency of String

    题意:有一个串s,n个串模式串t,问s的子串中长度最小的包含t k次的长度是多少 题解:把所有t建ac自动机,把s在ac自动机上匹配.保存每个模式串在s中出现的位置.这里由于t两两不同最多只有xsqr ...

  4. D. Mahmoud and Ehab and the binary string Codeforces Round #435 (Div. 2)

    http://codeforces.com/contest/862/problem/D 交互题 fflush(stdout) 调试: 先行给出结果,函数代替输入 #include <cstdio ...

  5. You Are Given a Decimal String... CodeForces - 1202B [简单dp][补题]

    补一下codeforces前天教育场的题.当时只A了一道题. 大致题意: 定义一个x - y - counter :是一个加法计数器.初始值为0,之后可以任意选择+x或者+y而我们由每次累加结果的最后 ...

  6. Check the string CodeForces - 960A

    A has a string consisting of some number of lowercase English letters 'a'. He gives it to his friend ...

  7. CF963D Frequency of String

    https://codeforces.com/problemset/problem/123/D 题目大意 给一个字符串 \(s\),每次询问一个字符串 \(m_i\) 和一个正整数 \(k_i\),问 ...

  8. Median String CodeForces - 1144E

    You are given two strings ss and tt, both consisting of exactly kk lowercase Latin letters, ss is le ...

  9. Minimal string CodeForces – 797C

    题目链接 题目难度: 1700rating 题目类型:string+贪心+STL 题目思路: 由于题目要求的最终结果是字典序最小的那个字符串,那么我们从贪心的从’a’开始查找字符串里是否存在,如果存在 ...

随机推荐

  1. django 简易博客开发 1 安装、创建、配置、admin使用

    首先贴一下项目地址吧  https://github.com/goodspeedcheng/sblog 到现在位置项目实现的功能有: 1.后台管理使用Admin ,前端显示使用bootstrap 2. ...

  2. 用"再生龙"Clonezilla 来克隆Linux系统

      上周公司买了5套高配置PC机来做测试用.上面要装好CentOS 加上一堆工具,有web的,数据库的,还有一些自己开发的工具.有些朋友肯定想,直接用kickstart不就行了,确实.kickstar ...

  3. RHEL 启动系统及故障排除

    一:Linux的启动过程: 开机加电自检->MBR引导(boot loader占446字节,分区列表64字节,magic占2字节)-->grub菜单(MBR是grub的第一个字段,第二个字 ...

  4. CentOS5 忘记root密码的解决办法

    方法/步骤   1 开机启动的时候,按“E”进入如下界面. 2 选择相应的内核,再次按“E”,出现下图,选择第二项,再次按“E”键 3 在尾部加:“空格+single”(如图),Enter.图如下: ...

  5. 聚合类新闻client产品功能点详情分析

    产品功能点 功能 今日头条 百度新闻 鲜果 ZAKER 媒体订阅 × √ ★ ★ 个性化内容推荐 ★ √ × × 个性化订阅(RSS) × × ★ × 视频新闻 × × × × 评论盖楼 √ √ √ ...

  6. 【SICP练习】149 练习4.5

    练习4-5 原文 Exercise 4.5. Scheme allows an additional syntax for cond clauses, ( => ). If evaluates ...

  7. 在调试C++程序是出现这个问题的解决方案illegal pure syntax, must be '= 0'

    笔者在调试c++的时候遇见了这个问题 E:\Data Struct\SqString\新建 文本文档.cpp(5) : error C2258: illegal pure syntax, must b ...

  8. mt7620 uboot

    我本机装的是64位Ubuntu, SDK 里提供的 buildroot-gcc342 是32位的,无法直接运行,需要先安装 gcc-multilib. sudo apt-get install gcc ...

  9. 我的package.json清单

    { "name": "lists", "version": "1.0.0", "main": &qu ...

  10. asp.net mvc + javascript生成下载文件

    近期做的是对现有项目进行重构.WEB FROM改成MVC,其实也算是推倒重来了. 里面有一个导出功能,将数据输出成txt文件,供下载.原先的做法是有一个隐藏的iframe,在这个iframe的页面中设 ...