<span>POJ - 1226 Substrings (后缀数组)</span>

传送门:POJ - 1226

这个题跟POJ - 3294  和POJ - 3450 都是一样的思路,一种题型。

POJ - 3294的题解可以见:https://www.cnblogs.com/lilibuxiangtle/p/12649853.html

题意:给你n个字符串,求最长子串的长度,要求子串或子串的翻转串在n个字符串中都出现。

题解:把每个字符串和字符串的翻转串连接起来,中间用不同且没出现过的字符隔开,然后再把n个字符串和翻转的串连到一起。然后后缀数组求出sa数组和height数组,用be数组标记每个位置的字符在哪个串中。二分长度,vis数组标记符合条件的串,cnt记录个数,如果cnt>=n则说明该长度可以,反之则不行。(重点!!vis及时标记 我憨憨的wa了好几发,找了快三个小时

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<queue>
  4 #include<iostream>
  5 #include<cmath>
  6 #include<cstring>
  7 using namespace std;
  8 
  9 //sa:字典序中排第i位的起始位置在str中第sa[i]  sa[1~n]为有效值
 10 
 11 //rnk:就是str第i个位置的后缀是在字典序排第几 rnk[0~n-1]为有效值
 12 
 13 //height:字典序排i和i-1的后缀的最长公共前缀  height[2~n]为有效值,第二个到最后一个
 14 
 15 const int INF=0x3f3f3f3f;
 16 const int maxn = 1e5+10;
 17 int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn];
 18 int rnk[maxn],height[maxn];
 19 char s[maxn];
 20 int r[maxn],n,L;
 21 int be[maxn],vis[110];
 22 
 23 int cmp(int *r,int a,int b,int k)
 24 {
 25     return r[a]==r[b]&&r[a+k]==r[b+k];
 26 }
 27 
 28 void getsa(int *r,int *sa,int n,int m)//n为添加0后的总长
 29 {
 30     int i,j,p,*x=wa,*y=wb,*t;
 31     for(i=0; i<m; i++)  wsf[i]=0;
 32     for(i=0; i<=n; i++)  wsf[x[i]=r[i]]++;
 33     for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
 34     for(i=n; i>=0; i--)  sa[--wsf[x[i]]]=i;
 35     p=1;
 36     j=1;
 37     for(; p<=n; j*=2,m=p){
 38         for(p=0,i=n+1-j; i<=n; i++)  y[p++]=i;
 39         for(i=0; i<=n; i++)  if(sa[i]>=j)  y[p++]=sa[i]-j;
 40         for(i=0; i<=n; i++)  wv[i]=x[y[i]];
 41         for(i=0; i<m; i++)  wsf[i]=0;
 42         for(i=0; i<=n; i++)  wsf[wv[i]]++;
 43         for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
 44         for(i=n; i>=0; i--)  sa[--wsf[wv[i]]]=y[i];
 45         swap(x,y);
 46         x[sa[0]]=0;
 47         for(p=1,i=1; i<=n; i++)
 48             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
 49     }
 50 }
 51 
 52 void getheight(int *r,int n)//n为添加0后的总长
 53 {
 54     int i,j,k=0;
 55     for(i=1; i<=n; i++)  rnk[sa[i]]=i;
 56     for(i=0; i<n; i++){
 57         if(k)
 58             k--;
 59         else
 60             k=0;
 61         j=sa[rnk[i]-1];
 62         while(r[i+k]==r[j+k])
 63             k++;
 64         height[rnk[i]]=k;
 65     }
 66 }
 67 
 68 bool check(int k)
 69 {
 70     memset(vis,0,sizeof(vis));
 71     int cnt=0;
 72     for(int i=2;i<=L;i++){
 73         if(height[i]>=k){
 74             if(!vis[be[sa[i]]]) cnt++;
 75             vis[be[sa[i]]]=1;               //就是这个地方卡了我快3个小时!!!
 76             if(!vis[be[sa[i-1]]]) cnt++;
 77             vis[be[sa[i-1]]]=1;
 78         }
 79         else {
 80             memset(vis,0,sizeof(vis));
 81             cnt=0;
 82         }
 83         if(cnt>=n) return 1;
 84     }
 85     return 0;
 86 }
 87 
 88 int main()
 89 {
 90     ios::sync_with_stdio(false);
 91     cin.tie(0);
 92     cout.tie(0);
 93     int t;
 94     cin>>t;
 95     while(t--){
 96         cin>>n;
 97         L=0;
 98         for(int i=0;i<n;i++){
 99             cin>>s;
100             int len=strlen(s);
101             for(int j=0;j<len;j++){
102                 r[L]=s[j];
103                 be[L++]=i;
104             }
105             r[L]=i+200;
106             be[L++]=i;
107             for(int j=len-1;j>=0;j--){
108                 r[L]=s[j];
109                 be[L++]=i;
110             }
111             if(i!=n-1) r[L]=i+n+200,be[L++]=i;
112         }
113         if(n==1) {
114             cout<<strlen(s)<<endl;
115             continue;
116         }
117         r[L]=0;
118         getsa(r,sa,L,500);
119         getheight(r,L);
120         int l=0,r=105,ans=0;
121         while(l<=r){
122             int mid=l+r>>1;
123             if(check(mid)) ans=mid,l=mid+1;
124             else r=mid-1;
125         }
126         cout<<ans<<endl;
127     }
128     return 0;
129 }

 

全部评论

相关推荐

02-12 20:22
重庆大学 Java
字节暑期刚入职四天,因为是年前,所以很多正职都放假走了,也就没有给我分配mt,然后有一个老哥在我来的时候给我发了一个landing手册,然后还有关于部门业务的白皮书,还有一些业务代码。然后本人是java面的,进来第一次接触go语言&nbsp;前面几天熟悉了一下go的语法和go的框架,可以读但是还不太会写,然后业务白皮书也看的很头疼,包括landing手册里要了解的很多东西说实话我看文档真的快看死了,一个嵌套一个,问题是我还完全不知道咋用这个我了解的东西,还有就是那个项目代码,那个老哥喊我去写写单测,熟悉一下go的语法,但也进行的很困难(这是我第一段实习,之前都是springboot那一套,真不太熟悉这个)想问问大家的建议,就是我从现在开始到在开年回来之前应该做些什么,我目前就一个想法&nbsp;就是复现一个landing手册上的go框架小项目&nbsp;就是相当于帮自己锻炼锻炼怎么写go&nbsp;或者各位大佬有没有更好的锻炼go语法的建议还有就是大家都在说vibe&nbsp;coding,那我应该怎么锻炼自己使用ai的能力,感觉我除了给一些需求然后它给我生成代码,好像就没别的用法了,那些什么工作流、拆解、skill啥的都不知道从哪一个地方开始,包括我现在正在实习,不知道精力该怎么分配,去网上想找找关于agent开发的一些学习流程,说实话,众说纷纭,有的是从python开始打基础然后系统学那些rag&nbsp;prompt&nbsp;langchain&nbsp;mcp等等,有的是说直接找一个github上的ai项目然后反复问ai,我确实有点迷茫,恳求各位大佬能留下你们宝贵的建议,我一定认真反复深刻学习有一说一&nbsp;我觉得字节饭挺好吃的!
Jasonnnnnn...:直接把项目代码喂给AI然后让它帮你分析,如果组里已经有一些流程图总结的话最好,没有的话自己画一个 Go的话其实只要把基础语法搞明白就行了,项目里很多都是直接让ai帮你写好然后自己稍微改下,不用学的特别深 ai的话,可以自己写一些md文件来搞点小东西,但除非你打算转算法,否则不用把rag langchain学的特别深,了解下就行了
字节跳动公司福利 1371人发布
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务