字符串问题
字符串问题
题目背景
Yazid 和 Tiffany 喜欢字符串问题。在这里,我们将给你介绍一些关于字符串的基本概念。
对于一个字符串 , 我们定义 表示 的长度。
接着,我们定义该串的子串 表示由 中从左往右数,第 个字符到第 个字符依次连接形成的字符串,特别地,如果 或 或 ,则 表示空串。
我们说两个字符串相等,当且仅当它们的长度相等,且从左至右各位上的字符依次相同。
我们说一个字符串 是 的**前缀**,当且仅当 。
两个字符串 相加 表示的是在 后紧挨着写下 得到的长度为 的字符串。
题目描述
现有一个字符串 。
Tiffany 将从中划出 个子串作为 A 类串,第 个()为 。
类似地,Yazid 将划出 个子串作为 B 类串,第 个()为 。
现额外给定 组支配关系,每组支配关系 描述了第 个 A 类串**支配**第 个 B 类串。
求一个**长度最大**的目标串 ,使得存在一个串 的分割 ()满足:
- 分割中的每个串 均为 A 类串:即存在一个与其相等的 A 类串,不妨假设其为 。
- 对于分割中所有相邻的串 (),都有存在一个 支配的 B 类串,使得该 B 类串为 的前缀。
方便起见,你只需要输出这个最大的长度即可。
特别地,如果存在无限长的目标串(即对于任意一个正整数 ,都存在一个满足限制的长度超过 的串),请输出 。
solution
首先考虑暴力建图:A向支配的B连,B向前缀包含它的连。然后跑拓扑序dp。 40‘(我这咋只有20)
用sam优化:用反串建,则x为x的后代的前缀。
那么可以把par树连起来,然后支配边照常连,边数2n 。80’
不能满分是因为如果b[i]>a[i],连边后可能两个B被压在了同一个节点,但是一个可以被支配,一个不行。
把一个sam节点上的所有串按长度排序,从长度小的开始连,每次当前点与它的上一个b点。相当于串了起来。
这样子如果A能支配某一个B1,那么他只会连到这个B1,然后再间接的连到一个比B1长的B2...
而如果B2是某个串的前缀,那么B1也是。
于是就好了。

1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 #define maxn 800005 10 using namespace std; 11 int T,na,nb,m,cnt,rt,la,al; 12 int head[maxn],tot,pl[maxn],f[maxn][22],out[maxn],top[maxn]; 13 long long dp[maxn];char ch[maxn]; 14 vector<int>G[maxn],p[maxn]; 15 struct node{int v,nex;}e[maxn*2]; 16 struct no{ 17 int par,nex[26],Max,ed; 18 }s[maxn]; 19 struct Node{ 20 int l,r,len; 21 }a[maxn],b[maxn]; 22 void Q(){ 23 for(int i=0;i<=cnt+na+nb;i++){ 24 head[i]=pl[i]=0; 25 out[i]=0;G[i].clear();p[i].clear(); 26 dp[i]=top[i]=0; 27 } 28 cnt=rt=la=1;tot=0; 29 memset(f,0,sizeof f); 30 memset(s,0,sizeof s); 31 } 32 void ins(int c,int id){ 33 int np=++cnt,p=la;la=np; 34 s[np].ed=id;s[np].Max=s[p].Max+1;pl[id]=cnt; 35 for(;p&&!s[p].nex[c];p=s[p].par)s[p].nex[c]=np; 36 if(!p)s[np].par=rt; 37 else { 38 int q=s[p].nex[c]; 39 if(s[q].Max==s[p].Max+1)s[np].par=q; 40 else { 41 int nq=++cnt; 42 s[nq].Max=s[p].Max+1;s[nq].par=s[q].par; 43 for(int i=0;i<26;i++)s[nq].nex[i]=s[q].nex[i]; 44 s[q].par=s[np].par=nq; 45 for(;s[p].nex[c]==q;p=s[p].par)s[p].nex[c]=nq; 46 } 47 } 48 } 49 void dfs(int k,int fa){ 50 f[k][0]=fa; 51 for(int i=0;i<G[k].size();i++)dfs(G[k][i],k); 52 } 53 bool cmp(int A,int B){ 54 int xa=A,xb=B; 55 if(A>cnt+na)A=b[A-cnt-na].len; 56 else A=a[A-cnt].len; 57 if(B>cnt+na)B=b[B-cnt-na].len; 58 else B=a[B-cnt].len; 59 return A<B||A==B&&xa>xb; 60 } 61 void add(int t1,int t2){ 62 e[++tot].v=t1;e[tot].nex=head[t2];head[t2]=tot; 63 out[t1]++; 64 } 65 void init(){ 66 scanf("%s",ch+1);int len=strlen(ch+1); 67 for(int i=len;i>=1;i--){ 68 ins(ch[i]-'a',i); 69 } 70 scanf("%d",&na);for(int i=1;i<=na;i++)scanf("%d%d",&a[i].l,&a[i].r),a[i].len=a[i].r-a[i].l+1; 71 scanf("%d",&nb);for(int i=1;i<=nb;i++)scanf("%d%d",&b[i].l,&b[i].r),b[i].len=b[i].r-b[i].l+1; 72 for(int i=1;i<=cnt;i++)G[s[i].par].push_back(i); 73 dfs(rt,0); 74 for(int j=1;j<=20;j++) 75 for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1]; 76 for(int i=1;i<=na;i++){ 77 int t=pl[a[i].l],L=a[i].len; 78 for(int j=20;j>=0;j--){ 79 int v=f[t][j];if(s[v].Max>=L)t=v; 80 } 81 p[t].push_back(cnt+i); 82 } 83 for(int i=1;i<=nb;i++){ 84 int t=pl[b[i].l],L=b[i].len; 85 for(int j=20;j>=0;j--){ 86 int v=f[t][j];if(s[v].Max>=L)t=v; 87 } 88 p[t].push_back(cnt+na+i); 89 } 90 for(int i=1;i<=cnt;i++)sort(p[i].begin(),p[i].end(),cmp); 91 92 for(int i=1;i<=cnt;i++){ 93 int lb=i; 94 for(int j=0;j<p[i].size();j++){ 95 int t=p[i][j]; 96 if(t>cnt+na)add(lb,t),lb=t; 97 else add(lb,t); 98 } 99 top[i]=lb; 100 } 101 for(int i=1;i<=cnt;i++) 102 if(s[i].par){ 103 add(top[s[i].par],i); 104 } 105 cin>>m; 106 for(int i=1,t1,t2;i<=m;i++){ 107 scanf("%d%d",&t1,&t2); 108 add(cnt+t1,cnt+na+t2); 109 } 110 al=cnt+na+nb; 111 } 112 void tp(){ 113 queue<int>q; 114 for(int i=1;i<=al;i++)if(!out[i])q.push(i); 115 while(!q.empty()){ 116 int x=q.front();q.pop(); 117 if(x>cnt&&x<=cnt+na)dp[x]+=a[x-cnt].len; 118 for(int i=head[x];i;i=e[i].nex){ 119 dp[e[i].v]=max(dp[e[i].v],dp[x]); 120 if(!(--out[e[i].v]))q.push(e[i].v); 121 } 122 } 123 for(int i=1;i<=al;i++)if(out[i]>0){puts("-1");return;} 124 long long ans=0; 125 for(int i=1;i<=al;i++)ans=max(ans,dp[i]); 126 cout<<ans<<endl; 127 } 128 int main(){ 129 cin>>T; 130 while(T--){ 131 Q(); 132 init(); 133 tp(); 134 } 135 return 0; 136 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构