随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

一、题目描述:
  给你 n 个字符串,求一个最长的片段,使得它在每个字符串中不重叠的出现过两次,输出这个片段的长度。

  共有 T 组数据,t10n10,每个字符串的长度 len 不超过 15000


 二、解题思路:

  二分答案,height 数组 O(n) 暴力判断,map 存字符串哈希值暴力判断在几个字符串中重复。时间复杂度 O(T×n×len×loglen)


 三、完整代码:

复制代码
  1 #include<bits/stdc++.h>
  2 #define K 15
  3 #define N 30010
  4 #define p 233323
  5 #define ll long long
  6 using namespace std;
  7 string s[K];
  8 ll T,n,m,ans,maxn,o=122,b[N],ha[K][N];
  9 ll len[K],tp[N],h[K][N],sa[K][N],rak[K][N];
 10 unordered_map <ll,ll> q,vis;
 11 
 12 struct ST{
 13     ll l,r,id;
 14     bool operator != (const ST &t)const{
 15         if(t.l!=l)    return 1;
 16         if(t.r!=r)    return 1;
 17         return 0;
 18     }
 19 }a[N],y[N];
 20 
 21 void get_height(ll x)
 22 {
 23     ll k=0;
 24     for(ll i=1;i<=len[x];i++)
 25     {
 26         if(k>=0)    k--;
 27         ll j=sa[x][rak[x][i]-1];
 28         while(s[x][j+k]==s[x][i+k])k++;
 29         h[x][rak[x][i]]=k+1;
 30     }
 31 }
 32 
 33 void qsort(ll x)
 34 {
 35     for(ll i=0;i<=m;i++)        tp[i]=0;
 36     for(ll i=1;i<=len[x];i++)    tp[a[i].r]++;
 37     for(ll i=1;i<=m;i++)        tp[i]+=tp[i-1];
 38     for(ll i=len[x];i>=1;i--)    y[tp[a[i].r]--]=a[i];
 39     for(ll i=0;i<=m;i++)        tp[i]=0;
 40     for(ll i=1;i<=len[x];i++)    tp[y[i].l]++;
 41     for(ll i=1;i<=m;i++)        tp[i]+=tp[i-1];
 42     for(ll i=len[x];i>=1;i--)    a[tp[y[i].l]--]=y[i];
 43 }
 44 
 45 void suffixsort(ll x)
 46 {
 47     for(ll i=1;i<=len[x];i++)
 48         rak[x][i]=s[x][i-1];
 49     for(ll i=len[x]+1;i<=len[x]*2;i++)
 50         rak[x][i]=0;
 51     for(ll j=1,o=122;j;j<<=1)
 52     {
 53         for(ll i=1;i<=len[x];i++)
 54         {
 55             a[i].id=i;
 56             a[i].l=rak[x][i];
 57             a[i].r=rak[x][i+j];
 58         }
 59         m=o;o=0;qsort(x);
 60         for(ll i=1;i<=len[x];i++)
 61             rak[x][a[i].id]=(o+=a[i]!=a[i-1]);
 62         if(o==len[x])    break;
 63     }
 64     for(ll i=1;i<=len[x];i++)
 65         sa[x][rak[x][i]]=i;
 66 }
 67 
 68 void build(ll x)
 69 {
 70     len[x]=s[x].length();
 71     maxn=max(maxn,len[x]);
 72     for(ll i=1;i<=len[x];i++)
 73         ha[x][i]=ha[x][i-1]*p+s[x][i-1];
 74     suffixsort(x),get_height(x);
 75 }
 76 
 77 bool update(ll d,ll val)
 78 {
 79     ll maxx=-1,minn=1e9;vis.clear();
 80     for(ll i=2;i<=len[d];i++)
 81     {
 82         if(h[d][i]>=val)
 83         {
 84             maxx=max(maxx,sa[d][i]);
 85             minn=min(minn,sa[d][i]);
 86             maxx=max(maxx,sa[d][i-1]);
 87             minn=min(minn,sa[d][i-1]);
 88         }
 89         else    if(maxx-minn>=val)
 90         {
 91             ll S=sa[d][i-1]-1,T=S+val;
 92             ll t=ha[d][T]-ha[d][S]*b[val];
 93             maxx=-1,minn=1e9;if(vis[t])continue;
 94             vis[t]=1;q[t]++;if(q[t]==n)return 1;
 95         }
 96     }
 97     if(maxx-minn<val)    return 0;
 98     ll S=sa[d][len[d]]-1,T=S+val;
 99     ll t=ha[d][T]-ha[d][S]*b[val];
100     if(vis[t])    return 0;    q[t]++;
101     if(q[t]==n)    return 1;    return 0;
102 }
103 
104 bool check(ll x)
105 {
106     q.clear();
107     for(ll i=1;i<=n;i++)
108         if(update(i,x))
109             return 1;
110     return 0;
111 }
112 
113 void solve()
114 {
115     cin>>n;b[0]=1;maxn=0;
116     for(ll i=1;i<=2e4;i++)
117         b[i]=b[i-1]*p;
118     for(ll i=1;i<=n;i++)
119         cin>>s[i],build(i);
120     ll l=1,r=maxn/2;ans=0;
121     while(l<=r)
122     {
123         ll mid=(l+r)>>1;
124         if(check(mid))
125         {
126             ans=mid;
127             l=mid+1;
128         }
129         else    r=mid-1;
130     }
131     cout<<ans<<'\n';
132 }
133 
134 int main()
135 {
136     ios::sync_with_stdio(false);
137     cin.tie(0);cout.tie(0);
138     cin>>T;
139     for(ll i=1;i<=T;i++)
140         solve();
141     return 0;
142 }
复制代码

四、写题心得:

  是一个比较板子的题,不过码量较大,但正是因为码量大所以用来练手效果极佳。有更智慧的方法,不过不想管了。加油!拜拜!

posted on   trh0630  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示