某摆烂蒟蒻选手在某大佬的不断督促要求下,终于开始学习字符串了—
首先开始学后缀自动机
看了好多好多篇博客,最终终于记下了代码,就是还不太理解变量的作用。
某帅气大佬说不需要记得代码,直接用板子就行,但是需要理解变量的作用,学会用,于是某摆烂蒟蒻选手又开始找博客学习,最终终于看到了勉勉强强理解了变量的作用
适合用来理解各种变量:[学习笔记] SAM——后缀自动机
洛谷:【模板】后缀自动机 (SAM)
struct node{
int ch[26];//有被自己蠢到,写成了char一直wa
int fa,len;
}d[maxn];
char s[MAX];
int z[maxn],len,las=1,siz=1;
ll ans;
vector<int>vec[maxn];
void insert(int x)
{
int p=las,np=las=++siz;
z[np]=1;
d[np].len=d[p].len+1;
for(;p&&!d[p].ch[x];p=d[p].fa)d[p].ch[x]=np;
if(!p)d[np].fa=1;
else
{
int q=d[p].ch[x];
if(d[q].len==d[p].len+1)d[np].fa=q;
else
{
int nq=++siz;
d[nq]=d[q];
d[nq].len=d[p].len+1;
d[q].fa=d[np].fa=nq;
for(;p&&d[p].ch[x]==q;p=d[p].fa)d[p].ch[x]=nq;
}
}
}
void dfs(int x)
{
for(int j:vec[x])
{
dfs(j);
z[x]+=z[j];
}
if(z[x]!=1)ans=max(ans,1ll*z[x]*d[x].len);
}
void solve()
{
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<=len;i++)insert(s[i]-'a');
for(int i=2;i<=siz;i++)vec[d[i].fa].push_back(i);
dfs(1);
printf("%lld\n",ans);
}
花空烟水流
struct node{
int ch[26];
int fa,len;
}d[maxn];
char s[MAX];
int n,m;
int las=1,siz=1;
bool vis[30];
vector<int>vec[maxn];
void insert(int x)
{
vis[x]=1;
int p=las,np=las=++siz;
d[np].len=d[p].len+1;
for(;p&&!d[p].ch[x];p=d[p].fa)d[p].ch[x]=np;
if(!p)d[np].fa=1;
else
{
int q=d[p].ch[x];
if(d[q].len==d[p].len+1)d[np].fa=q;
else
{
int nq=++siz;
d[nq]=d[q];
d[nq].len=d[p].len+1;
d[q].fa=d[np].fa=nq;
for(;p&&d[p].ch[x]==q;p=d[p].fa)d[p].ch[x]=nq;
}
}
}
bool dfs(int now,int cur,int l)
{
if(cur>l)return 0;
for(int i=0;i<26;i++)if(vis[i]&&!d[now].ch[i])return 1;
for(int i=0;i<26;i++)if(vis[i]&&dfs(d[now].ch[i],cur+1,l))return 1;
return 0;
}
bool check(int x)
{
if(dfs(1,1,x))return 1;
return 0;
}
stack<char>ans;
bool dfs1(int now,int cur,int l)
{
if(cur>l)return 0;
if(cur==l)
{
for(int i=0;i<26;i++)
{
if(vis[i]&&!d[now].ch[i])
{
ans.push(i+'a');
return 1;
}
}
return 0;
}
for(int i=0;i<26;i++)if(vis[i]&&dfs1(d[now].ch[i],cur+1,l))
{
ans.push(i+'a');
return 1;
}
return 0;
}
void solve1()
{
int l=1,r=n,cnt;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))r=mid-1,cnt=mid;
else l=mid+1;
}
dfs1(1,1,cnt);
while(!ans.empty())printf("%c",ans.top()),ans.pop();
puts("");
}
void solve()
{
scanf("%d%d%s",&n,&m,s+1);
for(int i=1;i<=n;i++)insert(s[i]-'a');
solve1();
}
洛谷:不同子串个数
struct node{
int ch[26];
int fa,len;
}d[maxn];
char s[maxn];
int n;
int las=1,siz=1;
ll ans;
void insert(int x)
{
int p=las,np=las=++siz;
d[np].len=d[p].len+1;
for(;p&&!d[p].ch[x];p=d[p].fa)d[p].ch[x]=np;
if(!p)d[np].fa=1;
else
{
int q=d[p].ch[x];
if(d[q].len==d[p].len+1)d[np].fa=q;
else
{
int nq=++siz;
d[nq]=d[q];
d[nq].len=d[p].len+1;
d[q].fa=d[np].fa=nq;
for(;p&&d[p].ch[x]==q;p=d[p].fa)d[p].ch[x]=nq;
}
}
}
void solve()
{
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++)insert(s[i]-'a');
for(int i=2;i<=siz;i++)ans+=(d[i].len-d[d[i].fa].len);
printf("%lld\n",ans);
}
AcWing:1283. 玄武密码
struct node{
int ch[4];
int fa,len;
}d[maxn];
int num[26];
int las=1,siz=1;
int n,m;
char s[MAX],t[MAX];
void insert(int x)
{
int p=las,np=las=++siz;
d[np].len=d[p].len+1;
for(;p&&!d[p].ch[x];p=d[p].fa)d[p].ch[x]=np;
if(!p)d[np].fa=1;
else
{
int q=d[p].ch[x];
if(d[q].len==d[p].len+1)d[np].fa=q;
else
{
int nq=++siz;
d[nq]=d[q];
d[nq].len=d[p].len+1;
d[q].fa=d[np].fa=nq;
for(;p&&d[p].ch[x]==q;p=d[p].fa)d[p].ch[x]=nq;
}
}
}
void solve()
{
num['E'-'A']=0;
num['S'-'A']=1;
num['W'-'A']=2;
num['N'-'A']=3;
scanf("%d%d%s",&n,&m,s+1);
for(int i=1;i<=n;i++)insert(num[s[i]-'A']);
while(m--)
{
scanf("%s",t+1);
int len=strlen(t+1);
int cur=1,now=1;
while(now<=len)
{
if(!d[cur].ch[num[t[now]-'A']])break;
cur=d[cur].ch[num[t[now]-'A']];
now++;
}
printf("%d\n",now-1);
}
}