1.30
一大早发现 通配符匹配 的做法被 Hack 了,之前分析的复杂度不对,dfs 朴素的复杂度好像是 \(n|s|^{k+1}\),跑满好像是 \(10^{46}\)ms,得跑 \(10^{37}\)s,整整 \(3.168808781×10^{29}\) 年😂😂😂,但是经过若干剪枝成功把水数据草过去了,但是正解显然又快又好。
把我,Shadow,Charlie_ 的做法 Hack 了,但是
神奇的 wang54321 没有被这份卡掉因为是哈希优化 bfs,太强了%%%
正解:
sto UU orz
感觉我是不是也要写一个做题纪要🤔🤔🤔但是反正我 2 月 2 号就走了啊那还是写个做题纪要吧
复习一下学过的知识点也挺好的。
怎么我现在的随笔已经排到 9 页了🤣🤣🤣看来还是太颓了。
在洛天依的怂恿下写了两道分块入门,差点被调死。看来还是太菜。
闪存遥遥领先寄
今天好像是效率最低的一集啊。
上午调了一上午数列分块入门2,最终调过了但是一无所获。
学了点 AC 自动机,然后只写完了板子,连洛谷简单版二都卡了半天,菜死了。
好像没了,就学了 AC 自动机。
AC自动机模板(确认有多少个子串出现过)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=6e6+5;
int n,m,cnt;
char s[N];
namespace AC_automaton
{
queue<int> q;
struct tree
{
int son[26],flag,fail;
}trie[N];
inline void insert(char* s)
{
int u=1,len=strlen(s);
for(int i=0;i<len;++i)
{
int v=s[i]-'a';
if(!trie[u].son[v]) trie[u].son[v]=++cnt;
u=trie[u].son[v];
}
trie[u].flag++;
}
inline void get_fail()
{
for(int i=0;i<26;++i)
trie[0].son[i]=1;
q.push(1);trie[1].fail=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;++i)
{
int v=trie[u].son[i];
int fail=trie[u].fail;
if(!v) {trie[u].son[i]=trie[fail].son[i];continue;}
trie[v].fail=trie[fail].son[i];
q.push(v);
}
}
}
inline int find(char* s)
{
int u=1,ans=0,len=strlen(s);
for(int i=0;i<len;++i)
{
int v=s[i]-'a';
int k=trie[u].son[v];
while(k>1 && trie[k].flag!=-1)
{
ans+=trie[k].flag,trie[k].flag=-1;
k=trie[k].fail;
}
u=trie[u].son[v];
}
return ans;
}
}
using namespace AC_automaton;
namespace IO
{
inline void close(){std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);}
inline void Fire(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
inline int read(){int s = 0,w = 1;char ch = getchar();while(ch<'0'||ch>'9'){ if(ch == '-') w = -1;ch = getchar();}while(ch>='0'&&ch<='9'){ s = s*10+ch-'0';ch = getchar();}return s*w;}
inline void write(int x){char F[200];int tmp=x>0?x:-x,cnt=0;;if(x<0)putchar('-') ;while(tmp>0){F[cnt++]=tmp%10+'0';tmp/=10;}while(cnt>0)putchar(F[--cnt]);}
}
using namespace IO;
signed main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
cnt=1;
n=read();
for(register int i=1;i<=n;++i)
{
cin>>s;
insert(s);
}
get_fail();
cin>>s;
cout<<find(s);
}
求子串在文章中出现过几次 LuoguP3796
#include<bits/stdc++.h>
using namespace std;
const int N=7e5+1;
int n,cnt,ans_cnt;
int ans[N],anss[N];
string s[205];
namespace AC_automaton
{
class
{
public:
int son[26];
int fail,num;
}trie[N];
inline void insert(string s,int id)
{
int u=0,len=s.size();
for(int i=0;i<len;++i)
{
int v=s[i]-'a';
if(!trie[u].son[v]) trie[u].son[v]=++cnt;
u=trie[u].son[v];
}
trie[u].num=id;
}
inline void get_fail()
{
queue<int> q;
for(register int i=1;i<=N;++i)
trie[i].fail=0;
for(register int i=0;i<26;++i)
if(trie[0].son[i])
q.push(trie[0].son[i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;++i)
{
if(trie[u].son[i])
{
trie[trie[u].son[i]].fail=trie[trie[u].fail].son[i];
q.push(trie[u].son[i]);
}
else
trie[u].son[i]=trie[trie[u].fail].son[i];
}
}
}
inline int find(string s)
{
memset(ans,0,sizeof(ans));
int u=0,res=0,len=s.size();
for(int i=0;i<len;++i)
{
int v=s[i]-'a';
u=trie[u].son[v];
for(int j=u;j;j=trie[j].fail) ans[trie[j].num]++;
}
for(int i=1;i<=n;++i)
{
if(res<ans[i])
{
res=ans[i];
ans_cnt=0;
}
if(res==ans[i]) anss[++ans_cnt]=i;
}
return res;
}
}
using namespace AC_automaton;
namespace IO
{
inline void close(){std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);}
inline void Fire(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
inline int read(){int s = 0,w = 1;char ch = getchar();while(ch<'0'||ch>'9'){ if(ch == '-') w = -1;ch = getchar();}while(ch>='0'&&ch<='9'){ s = s*10+ch-'0';ch = getchar();}return s*w;}
inline void write(int x){char F[20];int tmp=x>0?x:-x,cnt=0;;if(x<0)putchar('-') ;while(tmp>0){F[cnt++]=tmp%10+'0';tmp/=10;}while(cnt>0)putchar(F[--cnt]);}
}
using namespace IO;
signed main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
while((n=read())!=0)
{
memset(trie,0,sizeof(trie));
cnt=ans_cnt=0;
for(register int i=1;i<=n;++i)
cin>>s[i],insert(s[i],i);
cin>>s[n+1];
get_fail();
cout<<find(s[n+1])<<'\n';
for(int i=1;i<=ans_cnt;++i)
cout<<s[anss[i]]<<'\n';
}
}
Hack My Code!
早上那道题有双倍经验了,结果双倍经验就跟 UU 的Hack 效果一样,正向反向 dfs 搜索都是90,被卡死了。因为通配符数量为 1000。
今天洛天依居然猜到了我的密码,(其实很好猜的毕竟就是我壁纸),所以把密码换成了人名,好像机房知道能猜到人名的人不超过一个,当然就是我了😋😋😋感觉自己好小丑啊还把密码设成Ta的名字有点傻逼,但是我其实是很理智的,真的。
以后尽量少开小丑版块😓😓😓
Trump 期望 5 题,厉害