ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[atARC141F]Well-defined Abbreviation

2022-07-17 15:39:09  阅读:153  来源: 互联网

标签:子串 int ch defined void Abbreviation dep atARC141F define


取$T=S_{i}$,不断删除其任意子串$\in \{S_{j}\mid i\ne j\}$,最终应有$T\in \{S_{i},\empty\}$

关于该过程的实现,考虑建立AC自动机,并从前往后依次加入字符

若当前节点存在后缀为某子串,则删去该后缀,并跳到剩余部分对应位置

若$T=\empty$,则删除$S_{i}$可以以该过程代替,不妨去掉$S_{i}$,且这并不影响其余串

在此基础上,对于剩下的这些串(最终$T=S_{i}$),即两两不成子串关系

结论:$\exists T\iff \exists A,B,C$(其中$A\ne C$且均非空)满足$AB,BC\in \{S_{i}\}$

关于充分性,取$T=ABC$即可(注意到$A$和$C$均不存在$\{S_{i}\}$中的子串)

关于必要性,若满足此条件,对$|T|$从小到大归纳,并取出$T$中所有$\in \{S_{i}\}$的子串

注意到对应位置两两不交(不成子串关系&不存在$A,B,C$),进而可以将这些全部删除

具体的,记$T_{i}$表示删去第$i$个串,$T_{0}$表示全部删除,$f(T)$表示$T$所有可能的结果并

显然$f(T_{0})\subseteq f(T_{i})$,根据归纳两者大小均为$1$,进而$f(T)=\bigcup f(T_{i})=f(T_{0})$,即得证

关于该条件的判定,枚举其中$AB$对应串即后缀(借助$fail$指针)

若对应子树内存在多个串,显然总存在$C\ne A$,否则哈希比较两者即可

时间复杂度为$o(\sum |s_{i}|)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 2000005
 4 #define mod 998244353
 5 #define base 47
 6 #define ll long long
 7 int n,V,l,k,dep[N],ed[N],nex[N],pos[N],vis[N],cnt[N],ch[N][4];
 8 char s[N];queue<int>q;vector<int>v[N];
 9 void init(){
10     V=1;
11     memset(ch,0,sizeof(ch));
12 }
13 void add(int id){
14     k=1;
15     for(int c:v[id]){
16         if (!ch[k][c])ch[k][c]=++V,dep[V]=dep[k]+1;
17         k=ch[k][c];
18     }
19 }
20 void build(){
21     for(int i=0;i<4;i++){
22         if (!ch[1][i])ch[1][i]=1;
23         else nex[ch[1][i]]=1,q.push(ch[1][i]);
24     }
25     while (!q.empty()){
26         int k=q.front();q.pop();
27         if (!ed[k])ed[k]=ed[nex[k]];
28         for(int i=0;i<4;i++){
29             if (!ch[k][i])ch[k][i]=ch[nex[k]][i];
30             else nex[ch[k][i]]=ch[nex[k]][i],q.push(ch[k][i]);
31         }
32     } 
33 }
34 int main(){
35     scanf("%d",&n),init();
36     for(int i=1;i<=n;i++){
37         scanf("%s",s),l=strlen(s);
38         for(int j=0;j<l;j++)v[i].push_back(s[j]-'A');
39         add(i),ed[k]=l;
40     }
41     build();
42     for(int i=1;i<=n;i++){
43         l=0,k=pos[0]=1;
44         for(int c:v[i]){
45             k=ch[k][c];
46             if ((!ed[k])||(ed[k]==v[i].size()))pos[++l]=k;
47             else l-=ed[k]-1,k=pos[l];
48         }
49         if ((l)&&(l<v[i].size())){
50             printf("Yes\n");
51             return 0;
52         }
53         vis[i]=(l==v[i].size());
54     }
55     init();
56     for(int i=1;i<=n;i++)
57         if (vis[i])add(i);
58     build();
59     for(int i=1;i<=n;i++)
60         if (vis[i]){
61             l=0,k=pos[0]=1;
62             for(int c:v[i])k=pos[++l]=ch[k][c],cnt[k]++;
63             ed[pos[l]]=0;
64             for(l--;l;l--)ed[pos[l]]=((ll)base*ed[pos[l+1]]+v[i][l]+1)%mod;
65         }
66     for(int i=1;i<=n;i++)
67         if (vis[i]){
68             int s=1;l=pos[0]=0,k=1;
69             for(int c:v[i]){
70                 l++,k=ch[k][c];
71                 pos[l]=(pos[l-1]+(ll)s*(c+1))%mod,s=(ll)base*s%mod;
72             }
73             for(k=nex[k];k>1;k=nex[k])
74                 if ((cnt[k]>1)||(ed[k]!=pos[l-dep[k]])){
75                     printf("Yes\n");
76                     return 0;
77                 }
78         }
79     printf("No\n");
80     return 0;
81 } 
View Code

 

标签:子串,int,ch,defined,void,Abbreviation,dep,atARC141F,define
来源: https://www.cnblogs.com/PYWBKTDA/p/16486915.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有