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. Go --- 设计模式(工厂模式)

    简易工厂主要是用来解决对象“创建”的问题.以下的例子取自<大话设计模式>中第一章,实现一个可扩展的“计算器”.当增加新的功能时,并不需改动原来已经实现的算法.由于是简易工厂,所以我们还是需 ...

  2. poj 1258 Agri-Net(Prim)(基础)

    Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 44487   Accepted: 18173 Descri ...

  3. 理解Paxos Made Practical

    Paxos Made Practical 当一个组中一台机器提出一个值时,其它成员机器通过PAXOS算法在这个值上达成一致. Paxos分三个阶段. 第一阶段: 提出者会选出一个提议编号n(n> ...

  4. android 怎样将主菜单图标改成按安装时间排序

    1. 在 LauncherModel.java 中增加例如以下代码, 假设是KK Launcher3 ApplicationInfo要替换为AppInfo public static final Co ...

  5. 【iOS开发】-NSString的扩展使用

    第一:基本数据类型与字符串转换 //基本数据类型(int float,double char) 1)基本数据类型->NSString //1.int类型换换成字符串 int a = 88; NS ...

  6. Windows的MAX_PATH

    MAX_PATH的解释: 文件名最长256(ANSI),加上盘符(X:\)3字节,259字节,再加上结束符1字节,共260http://msdn.microsoft.com/en-us/library ...

  7. 编译FreePascal源代码(摘录自邮件询问)

    为了尝试编译FreePascal,我搜了官方文档,并给几位作者都发了邮件询问,目前结果如下: http://wiki.lazarus.freepascal.org/Getting_Lazarus#Co ...

  8. 并不对劲的bzoj4560:p3269:[JLOI2016]字符串覆盖

    题目大意 \(T\)(\(T\leq10\))组询问 每组询问给出一个字符串\(A\)(\(|A|\leq10^4\)),\(n\)(\(n\leq4\))个\(A\)的子串\(B_1,B_2,B_3 ...

  9. python-----群发图片

    使用wxpy库给3个人群发同一张图片 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/2/22 15:25 # @Author ...

  10. Python基础第七天

    一.内容 二.练习 练习1 题目:编写函数,函数执行的时间是随机的 图示: 代码: import time import random def func(): s = 1 l = [] for i i ...