求助,SAM全WA

SP694 DISUBSTR - Distinct Substrings

@[zing_Sing](/user/627307) 你复制节点那里为什么要加到52,加到26就可以了吧
by UncleSam_Died @ 2023-07-17 20:11:05


@[UncleSam_Died](/user/378996) 可是不是大小写好像都有吗,样例中没体现出来
by zing_Sing @ 2023-07-17 20:12:36


附上蒟蒻的蒟蒻,模板(很水,大佬随便看看吧) ```cpp #include<bits/stdc++.h> using namespace std; #define maxn 1000010 struct SuAM{ int link,len;//len记录长度,link记录连向哪个点 int ch[26];//记录每个字符出现的次数? }SAM[maxn<<1]; int siz,last; vector<int> SuffTree[maxn<<1]; inline void insert(const int c){//添加字符 int cur=++siz,p=last;//获取当前节点,获取上一个节点 SAM[cur].len=SAM[p].len+1;//当前节点的长度等于它的前缀(即上一个点)的长度加1 while(p!=-1&&!SAM[p].ch[c]){//如果父亲节点的字符集为空且父亲节点不为0(没有找到第一个点) SAM[p].ch[c]=cur;//更新父亲节点每个字符出现的次数? p=SAM[p].link;//通过link更新父亲节点,向上找 } if(p==-1)//如果当前节点的上一个节点是0号节点(当前插入第一个) SAM[cur].link=0;//把当前节点连向0号节点,把0号节点作为当前节点的父亲节点 else{ int q=SAM[p].ch[c];//用q来暂存p的出边 if(SAM[q].len==SAM[p].len+1)//如果当前节点的刚好为上一个节点+1 SAM[cur].link=q;//直接把这个节点连向上一个节点 else{ int copy=++siz;//新建一个点,把有关p的所有信息全部复制到新建节点中 SAM[copy].len=SAM[p].len+1;//新建节点的编号是p+1 SAM[copy].link=SAM[q].link;//新建节点的父节点更新为q的父节点 for(int i=0;i<26;i++)//遍历ch数组 SAM[copy].ch[i]=SAM[q].ch[i];//尝试连边 while(p!=-1&&SAM[p].ch[c]==q){ SAM[p].ch[c]=copy; p=SAM[p].link; } SAM[q].link=SAM[cur].link=copy;//更新父亲节点 } } last=cur;//更新last,把当前节点作为下一个节点的上一个节点 } char str[1000010]; int main(){ scanf("%s",&str);//以字符串的形式输入str SAM[0].link=-1;//初始化link,把第一号点连向-1 int len=strlen(str);//获取长度 for(int i=0;i<len;i++) insert(str[i]-'a');//依次插入每一个字符 return 0; } ```
by UncleSam_Died @ 2023-07-17 20:12:40


@[zing_Sing](/user/627307) 题中没说……你也可以认为128个都有……
by UncleSam_Died @ 2023-07-17 20:14:06


因为蒟蒻太弱了,读不懂洋文,理解有误勿喷
by UncleSam_Died @ 2023-07-17 20:14:31


@[UncleSam_Died](/user/378996) 可是我只写了大小写的情况也过了呀,代码如下: ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; ll t,n; struct tree { ll son[52],f,len; #define f(x) tr[x].f #define l(x) tr[x].len }tr[100005]; ll cnt=1,ls=1,ans[100005]; void add(ll x) { ll p=ls,np=ls=++cnt; l(np)=l(p)+1; for(;p&&!tr[p].son[x];p=f(p))tr[p].son[x]=np; if(!p)f(np)=1; else { ll q=tr[p].son[x]; if(l(q)==l(p)+1)f(np)=q; else { ll nq=++cnt; tr[nq]=tr[q]; l(nq)=l(p)+1; f(q)=f(np)=nq; for(;p&&tr[p].son[x]==q;p=f(p))tr[p].son[x]=nq; } } } string a; void dfs(ll id) { if(ans[id])return; ans[id]=1; for(ll i=0;i<=51;++i) if(tr[id].son[i]) dfs(tr[id].son[i]),ans[id]+=ans[tr[id].son[i]]; } ll wz(ll id) { if('a'<=id&&id<='z')return id-'a'; return id-'A'+26; } int main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin>>t; while(t--) { for(ll i=1;i<=1+2*n;++i) ans[i]=0,memset(tr[i].son,0,sizeof(tr[i].son)),f(i)=l(i)=0; cnt=ls=1; cin>>a; n=a.size(); for(ll i=0;i<n;++i)add(wz(a[i])); dfs(1); cout<<ans[1]-1<<'\n'; } } ```
by NATO @ 2023-07-17 20:16:12


@[NATO](/user/443649) 好吧,谢谢大佬指点,蒟蒻刚学SAM3ts
by UncleSam_Died @ 2023-07-17 20:17:04


```cpp #include<bits/stdc++.h> #define int long long using namespace std; const int N=1e4+5; int turn(int c){ if(c>='a'&&c<='z')return c-'a'; return c-'A'+26; } struct noi{ int ch[60],fa,len; }sam[N]; int tot,las; void addp(int c){ int p=las,np=las=++tot; sam[np].len=sam[p].len+1; for(;p&&!sam[p].ch[c];p=sam[p].fa)sam[p].ch[c]=np; if(!p)sam[np].fa=1; else{ int q=sam[p].ch[c]; if(sam[q].len==sam[p].len+1)sam[np].fa=q; else{ int nq=++tot; sam[nq]=sam[q]; sam[nq].len=sam[p].len+1; sam[q].fa=sam[np].fa=nq; for(;p&&sam[p].ch[c]==q;p=sam[p].fa)sam[p].ch[c]=nq; } } } int dp[N]; void dfs(int now){ if(dp[now])return; dp[now]=1; for(int i=0;i<=51;i++) if(sam[now].ch[i]) dfs(sam[now].ch[i]),dp[now]+=dp[sam[now].ch[i]]; } string s; signed main(){ int t; cin>>t; int n=0; while(t--){ for(int i=1;i<=2*n+1;i++){ memset(sam[i].ch,0,sizeof(sam[i].ch)); sam[i].len=sam[i].len=dp[i]=0; } tot=las=1; cin>>s; n=s.size(); for(int i=0;i<n;i++) addp(turn(s[i])); dfs(1); cout<<dp[1]-1<<"\n"; } return 0; } //目前位居亚军,加油! ``` @[zing_Sing](/user/627307) 改完了,是 $turn$函数的问题
by NATO @ 2023-07-17 20:38:12


@[UncleSam_Died](/user/378996) 谢谢dalao,真的有其他字符,把```turn```函数改了就对了%%%
by zing_Sing @ 2023-07-17 20:39:16


@[NATO](/user/443649) 谢谢dalao%%%
by zing_Sing @ 2023-07-17 20:40:02


| 下一页